/* Get Involved page.
   design/get-involved/docs/02-design-system.md (components, shape, type) and
   03-screens.md (the page order, the states, the narrow-phone rules).

   Colour comes from the site's tokens in tokens.css, never from the pack's
   screenshots: those were drawn against the pre-redesign brand palette and
   show a hotter pink and a greener yellow than the page uses. The pack's
   tokens.css ends with the name mapping this file follows.

   Everything is prefixed .gi- and scoped to .gi-page, so nothing here can
   reach another page's markup. */

.gi-page {
  /* Page-only tokens: the site has no equivalent for these, so they are
     declared here rather than added to the vendored tokens.css, which carries
     a "re-copy from the design pack" warning. */
  --paper: #F4F1EA;          /* the card preview: a physical card on a dark page */
  --paper-muted: #6C6874;    /* the preview's empty-state text only */
  --black: #0A0A0B;          /* logo tile, the Kickstarter and Preview chips */

  --gi-col: 720px;           /* desktop: the centred column */
  --gi-slant: 35px;          /* height of a band's slanted top edge */
  --gi-btn-h: 56px;
  --gi-input-h: 56px;
  --gi-tile: 48px;
  --gi-target: 44px;         /* nothing interactive is smaller */

  --gi-shadow-btn: 4px 4px 0;
  --gi-shadow-tile: 3px 3px 0;
  --gi-shadow-open: 6px 6px 0;
  --gi-shadow-ks: 8px 8px 0;
}

/* The column. The site's .container is 1280px wide; this page's content sits
   in 720 and the bands run edge to edge, so .container is narrowed inside the
   page rather than replaced. */
.gi-page .container {
  max-width: calc(var(--gi-col) + var(--gutter) * 2);
}

/* ------------------------------------------------------------------ type */

.gi-hero__title,
.gi-ks__title,
.gi-band__title,
.gi-card__title,
.gi-follow__title,
.gi-chip {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: .02em;
  line-height: .92;
  margin: 0;
}

/* ------------------------------------------------------------------ chips */

.gi-chip {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 2px 10px 0;
  font-size: 17px;
  letter-spacing: .04em;
  white-space: nowrap;
}

.gi-chip--yellow { background: var(--yellow); color: var(--ink); }
.gi-chip--pink   { background: var(--pink);   color: var(--ink); }
.gi-chip--black  { background: var(--black);  color: #FFF; }

/* ---------------------------------------------------------------- buttons */

.gi-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: var(--gi-btn-h);
  padding: 10px 18px;
  border: var(--border) solid transparent;
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1.05;
  letter-spacing: .03em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  /* So the on-screen keyboard cannot leave the button under itself. */
  scroll-margin-bottom: 96px;
}

.gi-btn--primary {
  background: var(--yellow);
  border-color: var(--ink);
  color: var(--ink);
  box-shadow: var(--gi-shadow-btn) var(--pink);
  font-size: 24px;
}

/* On the pink card the shadow has to be ink: yellow on pink is not a
   boundary, and the card is the loudest thing on the page. */
.gi-btn--on-pink { box-shadow: 5px 5px 0 var(--ink); }

.gi-btn--ghost {
  background: transparent;
  border-color: var(--text);
  color: var(--text);
}

/* "Starts {date}". Not a <button disabled> with a label that lies about what
   it does -- it is a <p>, so nothing focuses it or announces it as a control. */
.gi-btn--disabled {
  border-style: dashed;
  border-color: var(--line);
  color: var(--muted);
  cursor: default;
}

.gi-btn__chevron { margin-left: auto; }

.gi-icon {
  width: 1em;
  height: 1em;
  flex: none;
}

/* ------------------------------------------------------------------- hero */

.gi-hero__block {
  position: relative;
  overflow: hidden;
  background: var(--pink);
  padding-block: 28px 64px;
  /* The diagonal ink stripes. A gradient, not an image: no request, and it
     scales with the block. */
  background-image: repeating-linear-gradient(
    -55deg,
    rgba(19, 19, 22, .10) 0 14px,
    transparent 14px 40px
  );
}

/* The yellow lower edge, slanted. */
.gi-hero__block::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 22px;
  background: var(--yellow);
  clip-path: polygon(0 55%, 100% 0, 100% 100%, 0 100%);
}

.gi-hero__inner {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: start;
  gap: 16px;
}

.gi-hero__chip {
  grid-column: 1;
  justify-self: start;   /* a chip, not a bar: the grid track is 1fr */
  font-size: 20px;
  min-height: 30px;
}

.gi-hero__title {
  grid-column: 1 / -1;
  margin-top: 18px;
  font-size: 60px;
  line-height: .88;
  color: #FFF;
  /* Stroke under fill, so the letterforms keep their weight. */
  letter-spacing: .005em;        /* the comp's value for this one */
  -webkit-text-stroke: 5px var(--black);
  paint-order: stroke fill;
  text-shadow: 3.5px 3.5px 0 var(--pink);
  transform: rotate(-2.5deg);
  transform-origin: left bottom;
}

/* The comp hard-codes "Help make<br>Blurred Lines". This wraps naturally
   instead: the break is baked for one English string, and the French title is
   a different length, so a <br> in the copy would be wrong in one language or
   the other. The line count can differ from the frame here. */

.gi-hero__photo {
  grid-column: 2;
  grid-row: 1 / span 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 96px;
  height: 96px;
  background: var(--bg-2);
  border: var(--border) solid var(--line);
  color: var(--muted);
  transform: rotate(4deg);
  text-align: center;
}

.gi-hero__photo-icon { width: 28px; height: 28px; }
.gi-hero__photo-label { font-size: 12px; line-height: 1.2; }

.gi-hero__intro {
  margin: 34px 0 0;
  font-size: 20px;
  line-height: 1.55;
}

/* ------------------------------------------------------- Kickstarter card */

.gi-ks-wrap { padding-bottom: 56px; }

.gi-ks {
  margin-top: 36px;
  padding: 22px 20px 20px;
  background: var(--pink);
  border: var(--border) solid var(--ink);
  box-shadow: var(--gi-shadow-ks) var(--yellow);
  color: var(--ink);
}

.gi-ks__title {
  margin-top: 12px;
  font-size: 50px;
  color: var(--ink);
}

.gi-ks__body {
  margin: 14px 0 0;
  font-size: 19px;
  line-height: 1.5;
  color: var(--ink);
}

.gi-ks__action { margin-top: 20px; }
.gi-ks__btn { min-height: 64px; font-size: 26px; }

/* The email capture partial already knows the pink surface: `surface => pink`
   gives it the white field, the ink text and the site's own btn--on-pink. So
   nothing here restyles it.

   That button is ink-filled with white text and a yellow shadow, where the
   pack drew a yellow button with ink text. The site's component wins (the
   owner's ruling of October 23, 2026) and it is the stronger of the two on
   this fill: white on ink is 19.8:1. See BUILD-NOTES.md, D7. */
.gi-ks .ec { margin: 0; }

/* ------------------------------------------------------------------ bands */

.gi-band {
  position: relative;
  padding-block: 72px 64px;
  background: var(--bg);
}

.gi-band--alt { background: var(--bg-1); }

/* The slanted top edge, drawn in the band's own colour over the one above. */
.gi-band::before {
  content: "";
  position: absolute;
  top: calc(var(--gi-slant) * -1 + 1px);
  left: 0;
  right: 0;
  height: var(--gi-slant);
  background: inherit;
  clip-path: polygon(0 100%, 100% 0, 100% 100%, 0 100%);
}

.gi-band__title {
  margin: 14px 0 24px;
  font-size: 56px;
}

/* ------------------------------------------------------------------ meter */

.gi-meter {
  display: flex;
  gap: 4px;
  margin: 0;
}

.gi-meter__bar {
  width: 34px;
  height: 8px;
  background: var(--line);
}

.gi-meter__bar.is-on { background: var(--yellow); }

/* ------------------------------------------------------------- role cards */

.gi-cards {
  display: grid;
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* One grid at every width, so the chip can sit top-right beside the tile on a
   phone and between the title and the body on a desktop without the markup
   carrying it twice. A card with no chip leaves that track empty. */
.gi-card {
  display: grid;
  grid-template-columns: var(--gi-tile) 1fr;
  grid-template-areas:
    "tile   chip"
    "title  title"
    "body   body"
    "action action";
  column-gap: 12px;
  padding: 20px;
  background: var(--bg-1);
  border: var(--border) solid var(--line);
}

/* A card always sits on the other ground from its band, so it is always
   lighter or darker than what is behind it. */
.gi-band--alt .gi-card { background: var(--bg); }

.gi-tile {
  grid-area: tile;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--gi-tile);
  height: var(--gi-tile);
  border: var(--border) solid var(--ink);
  color: var(--ink);
}

.gi-tile__icon { width: 24px; height: 24px; }

.gi-tile--pink   { background: var(--pink); }
.gi-tile--yellow { background: var(--yellow); }
/* The only tile whose glyph is not ink: purple is too dark for it (3.1:1),
   white is 5.9:1. */
.gi-tile--purple { background: var(--purple); color: #FFF; }

.gi-card__chip {
  grid-area: chip;
  justify-self: end;
  align-self: start;
  margin-top: 4px;
}

.gi-card__title {
  grid-area: title;
  margin: 18px 0 0;
  font-size: 36px;
  /* The tight end of the display face's range (02-design-system.md says .005
     to .07em). At .02em "Host a playtest at home" wraps where the comp holds
     it on one line. */
  letter-spacing: .005em;
}

.gi-card__body {
  grid-area: body;
  margin: 12px 0 0;
  font-size: 18px;
  line-height: 1.45;
}

.gi-card__action {
  grid-area: action;
  display: grid;
  gap: 12px;
  margin-top: 20px;
}

/* ------------------------------------------------------------- follow row */

.gi-follow { padding-block: 56px; }

.gi-follow__title {
  margin-bottom: 18px;
  font-size: 34px;
  color: var(--accent-text);
}

/* The panel variant is shaped for the mobile menu, where it sits under the
   nav links behind a rule and the menu's own side padding. Here it is a
   section of its own, so both are cleared. */
.gi-page .social--panel .social__list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 0;
  padding: 0;
  border-top: 0;
  list-style: none;
}

.gi-page .social--panel .social__link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding: 0 16px;
  border: var(--border) solid var(--text);
  color: var(--text);
  text-decoration: none;
  font-weight: 700;
}

.gi-page .social--panel .social__link svg { width: 20px; height: 20px; }

/* ------------------------------------------------------------ narrow phones
   The comps are 390. These rules are what hold the page together at 360 and
   320, and no frame shows them (03-screens.md). */

/* The hero title is NOT shrunk. 02-design-system.md fixes it at 60 px and
   03-screens.md says that if it touches the edge at 320 the owner is to be
   told rather than it being quietly made smaller. Measured at 320: the
   rotated box ends at 302 px in both languages, so it clears the viewport but
   sits about 2 px past the 20 px gutter. Reported in BUILD-NOTES.md; it is
   the owner's call, not a thing to fix in CSS. */

@media (max-width: 360px) {
  .gi-ks__title   { font-size: 40px; }
  .gi-band__title { font-size: 44px; }
  .gi-card__title { font-size: 30px; }

  /* The empty placeholder tile is the first thing to go: the title needs the
     width more than a bracketed box does. A real photo stays -- it is content,
     and the hero reads as a person asking for help. Measured at 320: both
     languages still fit with it in place. */
  .gi-hero__photo:not(.gi-hero__photo--real) { display: none; }
}

/* Long handles and compound words wrap instead of widening the page. */
.gi-page { overflow-wrap: break-word; }

/* ---------------------------------------------------------------- desktop */

@media (min-width: 768px) {
  .gi-hero__block { padding-block: 40px 96px; }
  .gi-hero__block::after { height: 40px; }

  .gi-hero__title {
    font-size: 104px;
    -webkit-text-stroke-width: 8px;
    margin-top: 10px;
  }

  .gi-hero__photo { width: 112px; height: 112px; }
  .gi-hero__intro { font-size: 22px; }

  .gi-ks {
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: 32px;
    align-items: start;
    padding: 28px;
  }

  .gi-ks__title  { font-size: 56px; }
  .gi-ks__action { margin-top: 0; }

  .gi-band__title { font-size: 64px; }
  .gi-cards { gap: 24px; }

  /* A closed card is one row: the tile, the text, then a 200 px button at the
     right, both outer columns centred against the text. The chip moves out of
     the corner and into the text column, under the title. */
  .gi-card {
    grid-template-columns: var(--gi-tile) 1fr 200px;
    grid-template-areas:
      "tile title  action"
      "tile chip   action"
      "tile body   action";
    column-gap: 20px;
    padding: 24px;
  }

  .gi-tile         { align-self: center; }
  .gi-card__title  { margin: 0; }
  .gi-card__chip   { justify-self: start; margin: 8px 0 0; }
  .gi-card__action { margin-top: 0; align-self: center; }
}

/* ------------------------------------------------------------------ print
   Nobody prints this page, but a saved copy should not be a wall of pink. */

@media print {
  .gi-hero__block { background: none; }
  .gi-hero__title { color: var(--ink); -webkit-text-stroke: 0; text-shadow: none; }
}

/* ======================================================================
   FORMS (phase 4)
   03-screens.md for the order and the states, 02-design-system.md for the
   controls. The panel is rendered open and closed by accordion.js, so with
   no script every form is visible and still posts.
   ====================================================================== */

/* An open card takes a --text border and a pink shadow, and the form sits
   below a divider of the same weight. */
.gi-card:has(.gi-card__open[aria-expanded="true"]) {
  border-color: var(--text);
  box-shadow: var(--gi-shadow-open) var(--pink);
}

.gi-card__panel {
  grid-column: 1 / -1;
  margin-top: 20px;
  padding-top: 20px;
  border-top: var(--border) solid var(--text);
}

.gi-form {
  display: grid;
  gap: 24px;
}

.gi-field { display: grid; gap: 8px; }

.gi-field__label,
.gi-group > .gi-field__label {
  font-size: 18px;
  font-weight: 700;
  line-height: 1.35;
}

.gi-input {
  width: 100%;
  min-height: var(--gi-input-h);
  padding: 10px 16px;
  background: var(--input-bg);
  border: var(--border) solid var(--input-border);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 20px;
}

.gi-textarea {
  min-height: 132px;
  padding: 12px 16px;
  line-height: 1.45;
  resize: vertical;
}

.gi-input:focus-visible,
.gi-opt:focus-within,
.gi-check:focus-within {
  outline: 3px solid var(--focus);
  outline-offset: 4px;
}

.gi-help,
.gi-counter {
  margin: 0;
  color: var(--muted);
  font-size: 16px;
}

.gi-counter { text-align: right; }
.gi-counter.is-over { color: var(--error); font-weight: 700; }

/* ---------------------------------------------------------- choice groups */

.gi-group { margin: 0; padding: 0; border: 0; }
.gi-group > .gi-field__label { margin-bottom: 8px; padding: 0; }

.gi-group__opts { display: grid; gap: 12px; }
.gi-group--tile .gi-group__opts { grid-template-columns: 1fr 1fr; }
.gi-group--kind .gi-group__opts { grid-template-columns: .9fr 1fr 1.2fr; }
.gi-group--pill .gi-group__opts { display: flex; flex-wrap: wrap; }

/* One control, four shapes. The input stays the real control and keeps its
   place in the accessibility tree; it is the box around it that is drawn. */
.gi-opt {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--gi-target);
  padding: 10px 14px;
  background: var(--bg-2);
  border: var(--border) solid var(--line);
  color: var(--text);
  font-size: 18px;
  line-height: 1.3;
  cursor: pointer;
}

.gi-opt--row  { min-height: 56px; }
.gi-opt--tile { min-height: 52px; justify-content: center; text-align: center; }
.gi-opt--kind { min-height: 64px; justify-content: center; text-align: center; font-size: 15px; }
.gi-opt--pill { min-height: 48px; }

/* The native input covers its own box: focus, keyboard and announcement are
   the browser's, and the drawn state follows :checked. */
.gi-opt input,
.gi-check input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.gi-opt__mark {
  display: none;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: var(--border) solid currentColor;
}

/* Rows and pills carry an indicator; tiles and the kind selector ARE the
   indicator, because they fill when chosen. That is what the comps draw. */
.gi-opt--row .gi-opt__mark,
.gi-opt--pill .gi-opt__mark { display: inline-flex; }
.gi-opt--row:has(input[type="radio"]) .gi-opt__mark { border-radius: 999px; }

.gi-opt__tick { width: 18px; height: 18px; opacity: 0; }

.gi-opt:has(input:checked) {
  background: var(--yellow);
  border-color: var(--ink);
  color: var(--ink);
  font-weight: 700;
  box-shadow: var(--gi-shadow-btn) var(--pink);
}

.gi-opt--tile:has(input:checked),
.gi-opt--kind:has(input:checked) { box-shadow: var(--gi-shadow-tile) var(--pink); }
.gi-opt:has(input:checked) .gi-opt__tick { opacity: 1; }

/* ------------------------------------------------------------- checkboxes */

.gi-check {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  font-size: 18px;
  line-height: 1.35;
  cursor: pointer;
}

.gi-check__box {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: var(--border) solid var(--text);
}

.gi-check__tick { width: 18px; height: 18px; opacity: 0; color: var(--ink); }

.gi-check:has(input:checked) .gi-check__box { background: var(--yellow); border-color: var(--yellow); }
.gi-check:has(input:checked) .gi-check__tick { opacity: 1; }

/* --------------------------------------- suggestion box: the extra parts */

.gi-guide {
  padding: 16px;
  border: var(--border) dashed var(--line);
  background: var(--bg);
}

.gi-guide__title {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-size: 22px;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--accent-text);
}

.gi-guide__list { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.gi-guide__list li { display: flex; gap: 10px; font-size: 17px; line-height: 1.4; }
.gi-guide__tick { flex: none; width: 18px; height: 18px; margin-top: 3px; color: var(--yellow); }

.gi-credit__title { margin: 0; font-size: 18px; font-weight: 700; }

.gi-terms {
  padding: 14px;
  border: var(--border) solid var(--line);
  color: var(--muted);
  font-size: 15px;
  line-height: 1.5;
}

/* The no-credit box dims the pair it drops. The server drops those values
   whatever is posted, so this is a cue, not the rule; involve.js disables
   the fields properly in phase 6. */
.gi-form:has(input[name="no_credit"]:checked) .gi-credit__title,
.gi-form:has(input[name="no_credit"]:checked) .gi-field:has(#suggest-credit_name),
.gi-form:has(input[name="no_credit"]:checked) .gi-field:has(#suggest-credit_city) {
  opacity: .55;
}

/* ------------------------------------------------------------ the preview */

.gi-preview-wrap { display: grid; justify-items: start; }
.gi-preview__chip { position: relative; z-index: 1; margin-bottom: -3px; }

.gi-preview {
  width: 100%;
  padding: 18px;
  background: var(--paper);
  border: var(--border) solid var(--ink);
  box-shadow: var(--gi-shadow-open) var(--pink);
  color: var(--ink);
}

.gi-preview__text { margin: 0; font-size: 22px; font-weight: 700; line-height: 1.35; }
.gi-preview__empty { color: var(--paper-muted); font-weight: 400; }

.gi-preview__byline {
  margin: 14px 0 0;
  padding-top: 10px;
  border-top: 2px solid var(--ink);
  font-family: var(--font-display);
  font-size: 20px;
  letter-spacing: .03em;
  text-transform: uppercase;
}

/* ------------------------------------------- what the chosen kind shows */

/* Everything kind-specific is hidden, then the checked radio brings its own
   back. :has() means the switch works with no script. */
.gi-form [data-gi-only] { display: none; }

.gi-form:has(.gi-group--kind input[value="card"]:checked)     [data-gi-only~="card"],
.gi-form:has(.gi-group--kind input[value="category"]:checked) [data-gi-only~="category"],
.gi-form:has(.gi-group--kind input[value="feedback"]:checked) [data-gi-only~="feedback"] {
  display: block;
}

.gi-form:has(.gi-group--kind input[value="card"]:checked) .gi-preview-wrap[data-gi-only~="card"] {
  display: grid;
}

/* Every role but the suggestion box has no kind selector and nothing
   kind-specific, so nothing is hidden there. */
.gi-form:not(:has(.gi-group--kind)) [data-gi-only] { display: block; }

/* ----------------------------------------------------- honeypot and send */

/* Off-screen rather than display:none: a bot that skips hidden fields should
   still find it, while nobody sees it, tabs to it or hears it. */
.gi-hp {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.gi-form__send { margin-top: 4px; }

/* --------------------------------------------------------- narrow phones */

@media (max-width: 360px) {
  /* Two-column grids become one, and the kind selector stacks: "Feedback or
     other" clips otherwise, and the French is the worst case. */
  .gi-group--tile .gi-group__opts,
  .gi-group--kind .gi-group__opts { grid-template-columns: 1fr; }
  .gi-opt--kind { min-height: 52px; }
}

/* --------------------------------------------------------------- desktop */

@media (min-width: 768px) {
  .gi-card__panel { margin-top: 24px; }

  /* Players go four across. */
  .gi-group--tile[data-gi-field="players"] .gi-group__opts { grid-template-columns: repeat(4, 1fr); }

  /* The contact pair and the credit pair sit side by side; everything else
     runs the full width of the panel. */
  .gi-form {
    grid-template-columns: 1fr 1fr;
    column-gap: 22px;
  }

  .gi-form > * { grid-column: 1 / -1; }

  .gi-form > .gi-field:has(input[name="name"]),
  .gi-form > .gi-field:has(input[name="credit_name"]) { grid-column: 1; }

  .gi-form > .gi-field:has(input[name="email"]),
  .gi-form > .gi-field:has(input[name="credit_city"]) { grid-column: 2; }
}

/* The chevron flips when the card opens. Driven by aria-expanded, so the
   state is in the markup and the CSS only reflects it. */
.gi-card__open[aria-expanded="true"] .gi-btn__chevron { transform: rotate(180deg); }

/* The no-JS outcome panels. involve.js builds the full success panel (with the
   optional sign-up) in phase 6; these are what the 303 round trip shows. */

.gi-success {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.gi-success__icon { flex: none; width: 28px; height: 28px; color: var(--yellow); }
.gi-success__text { margin: 0; font-size: 22px; font-weight: 700; line-height: 1.35; }

.gi-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 20px;
  padding: 14px;
  background: var(--bg);
  border: var(--border) solid var(--error);
  font-size: 18px;
  font-weight: 700;
  line-height: 1.4;
}

.gi-banner__icon { flex: none; width: 22px; height: 22px; margin-top: 2px; color: var(--error); }

/* The error line under a field, and the dimmed form while it sends. */

.gi-error {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0;
  color: var(--error);
  font-size: 17px;
  font-weight: 700;
  line-height: 1.35;
}

.gi-error .gi-icon { flex: none; width: 19px; height: 19px; margin-top: 2px; }

.gi-input[aria-invalid="true"] { border-color: var(--error); }

/* The fields dim and stop taking input while sending; the form keeps its
   height so nothing jumps. The button stays readable: it is the thing that
   just changed. */
.gi-form.is-sending > *:not(.gi-form__send) {
  opacity: .55;
  pointer-events: none;
}

/* At 200% zoom on a phone (~195 CSS px) the Kickstarter button's label is the
   only thing that cannot fit: the site's shared .btn keeps its text on one
   line. Allowed to wrap here rather than changing the component, which every
   other page also uses. The same label overflows at that zoom on the home
   page; that is the owner's call, not this page's to make.
   Nothing below 320 px is a WCAG reflow requirement -- 320, 360 and 390 all
   fit with every form open -- but 200% zoom is on the pack's checklist. */
.gi-ks .btn,
.gi-ks .btn span { white-space: normal; }

/* A grid track is min-content wide by default, so a chip that refuses to wrap
   ("Starts January 4") can push a card wider than the screen. Below 400 px the
   chips may wrap, and nothing in a card may claim more than its share. At the
   comp's 390 px they still fit on one line, so this changes nothing visible
   there -- it only stops the page scrolling sideways at 200% zoom. */
.gi-card > * { min-width: 0; }

@media (max-width: 400px) {
  .gi-chip { white-space: normal; }
}

/* The real photo fills the slot the placeholder tile used to occupy: same
   size, same 3 px border, same 4-degree tilt. object-fit keeps the face
   centred whatever the file's aspect ratio turns out to be. */
.gi-hero__photo--real {
  display: block;
  object-fit: cover;
  background: var(--bg-2);
  padding: 0;
}
