/* ── THE OPTION CARD, THE ONE STYLESHEET FOR IT ────────────────────────────────────────────────

   THE QUEUE, 2026-09-19, "The options block draws the customer form's own cards". Tim: "the best
   way is to have the layout look the same as how it would inside of the configurator, so you know
   exactly what it's going to look like", and the item's own wording is "not a lookalike, THE
   FORM'S OWN CARD, one rendering per CORE RULES".

   app/shared/option-card.js became the one BUILDER on the same day. This is the other half: the
   portal does not load product-page.css and never should - it is the configurator's stylesheet -
   so the card's rules moved out of it into here, and both surfaces link this file. That is the
   pattern estimate-render.css already set, for the same reason and in the same words: two
   surfaces printing one thing share the rule.

   NOTHING IN HERE CHANGED IN THE MOVE. The computed style of every option card, label, price,
   swatch, photo and stacked figure on five products, including both live clients, was captured
   before and compared after, twice: once for the move and once at the end of the item. Each rule
   keeps the comment it was written with, because the reason a declaration exists is the part that
   gets lost when a file moves.

   IT LOADS BEFORE product-page.css, so anything that stylesheet still says about a card - the
   responsive rules at its breakpoints, the photo-well variables - continues to win, which is what
   made the move safe to do in one step.

   AND IT NAMES TOKENS RATHER THAN COLOURS, which is the reason no fallback is written here. The
   configurator defines every one of them. THE PORTAL DEFINES THEM FOR ITSELF, in editor-styles.js,
   scoped to the pane: a fallback list in this file would be a second palette living beside the
   rules, and the first attempt at exactly that moved four computed values on the configurator.
   Measured, reverted, and done the other way.
*/

/* ── Option cards (finish selection) ─────────────────────────────────────── */

.option-grid {
  display: grid;
  /* THE COUNT IS THE CLIENT'S, VIA --option-cols, AND THE STYLESHEET DECIDES WHETHER IT FITS
     (2026-09-09). It used to be written inline as a resolved template, which outranks every rule
     here and is why this level never collapsed at any width. */
  grid-template-columns: repeat(var(--option-cols, 2), minmax(0, 1fr));
  gap: 8px;
  /* ── EVERY OPTION IN A SET OCCUPIES THE SAME CELL (2026-09-10, THE QUEUE) ────────────────────
     Tim: "We need a global fix that will work for any type of radio set up so that the price isn't
     only half in the box in custom colour."
     THE WIDTH WAS NEVER THE FAULT. Measured on MORPHD's colour question before anything was
     changed: every option is 136px wide already, because the track above is `1fr`. The heights were
     98 for a swatch and 56 for the one word, and the swatches sit in FULL rows while Custom Colour
     is alone on the last one. A grid item stretches to its ROW, and a row with one card in it is as
     tall as that card, so nothing was there to stretch against. That is the whole cause, and it is
     why this is one declaration rather than a height on the card.
     `1fr` on the auto rows makes every row in the set the height of the tallest, so an option is the
     same size as its siblings whether it carries a swatch, a photograph, a word or a wrapped label.
     A TEXT-ONLY SET DOES NOT BECOME TALL, which establish 3 asks about: the tallest row in a set of
     plain words is still a plain word. Only a MIXED set levels up, which is the thing being asked
     for. */
  grid-auto-rows: 1fr;
}

/* AN UNCHOSEN OPTION IS A CONTROL LIKE ANY OTHER. The CHOSEN one keeps the client's colour, which
   is selection state and is the one place a brand colour on a control border is the point - see
   `.option-card:has(input:checked)` below. */
.option-card {
  border: 1px solid var(--control-border);
  border-radius: var(--radius);
  padding: 12px 14px;
  cursor: pointer;
  background: var(--white);
  display: flex;
  align-items: flex-start;
  gap: 10px;
  transition: border-color 0.15s, background 0.15s;
  /* AND EVERYTHING THE OPTION CARRIES SITS INSIDE THAT CELL, which is the second half of the rule
     and the half Tim actually saw (2026-09-10). `.option-price` is nowrap with `margin-left: auto`,
     which is right in a wide card and cannot work in a 136px one: measured, the price was INSIDE
     the element and its box OVERFLOWED the card's right edge, so it read as half in and half out.
     Establish 1 asked which of those two faults it was; it is the second, and a card that is
     allowed to wrap fixes it without moving the price out of the option it belongs to.
     Wrapping only ever engages when the row genuinely does not fit, so a wide card is unchanged. */
  flex-wrap: wrap;
}

/* Hide the actual radio button - selection is shown via card border/bg */
.option-card input[type="radio"] {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}

/* ── A CHOSEN OPTION IS DISTINCT FROM WHATEVER IT SITS IN (2026-09-19, THE QUEUE, "Folding
   ── follow-ups: a selected card blends into its panel") ─────────────────────────────
   Tim, on the demo fitout: "The colour for the selected radio button is the same as the colour of
   the box, so it doesn't stand out at all."

   IT WAS LITERALLY THE SAME COLOUR. The chosen card was --teal-pale flat, and a form panel's tint
   is made from --teal-pale as well, so inside a drawer panel the chosen Drawer slides card and
   the panel behind it were the same paint. Nothing was wrong with the rule until the form grew
   tinted panels underneath it; the two had never been on screen together.

   SO THE SELECTION MOVES OFF THE PALEST STEP AND ONTO THE BRAND COLOUR ITSELF, mixed light
   against white. No panel tint can reach it at any depth, because a panel is only ever
   --teal-pale with a little ink in it, while this is --teal. AND AN INSET RING, so the chosen
   card reads as chosen on a screen with the brightness down and for a reader who cannot separate
   two tints of one hue at all.

   STILL THE CLIENT'S OWN COLOUR and never one written here: both values come from the client
   palette, so MORPHD's chosen card is MORPHD's. */
.option-card:has(input:checked) {
  border-color: var(--teal);
  background: color-mix(in srgb, var(--teal, #0f766e) 12%, var(--white, #ffffff));
  box-shadow: inset 0 0 0 1px var(--teal);
}

.opt-label {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--dark);
  text-transform: none;
}

.opt-sub {
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 2px;
  font-weight: 300;
  text-transform: none;
}

/* Descriptions never appear inside option cards -- they move to the hint line below the group */
.option-card .opt-sub {
  display: none;
}

.option-price {
  margin-left: auto;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--teal);
  /* THE PRICE NEVER LEAVES ITS OWN BOX (2026-09-10, THE QUEUE). This was `white-space: nowrap`,
     which is right in a wide row and cannot work in a narrow one: measured on MORPHD's colour
     question, the price element was 125px inside a 108px content box and hung 5px past the card's
     right edge, which is Tim's "only half in the box". Nowrap made the element wider than the space
     it had and there was no width at which it would ever have fitted.
     Wrapping engages ONLY when the line genuinely does not fit, so every wide card - the tick box
     rows, every two-column set on Oceanside - keeps its price on one line exactly as before. The
     `max-width` is the guarantee rather than the wrap: a single unbreakable token still cannot
     exceed the cell. */
  white-space: normal;
  max-width: 100%;
  align-self: center;
  text-transform: none;
  letter-spacing: normal;
}

/* 3-column option grid - used for lock finish image cards */
.option-grid--3 {
  display: flex;
  justify-content: center;
  gap: 8px;
}

/* Stacked image+label card - image on top, label below */
.option-card--stacked {
  flex-direction: column;
  align-items: stretch;
  padding: 0;
  overflow: hidden;
  gap: 0;
}

/* THE ONE EXCEPTION to the single max height (2026-08-09, brief Task 12): a radio option badge
   takes one photo and sizes to the BADGE. The card is the unit here, not the photo - a 210px photo
   in a 120px card would make the card, and a row of cards is a picker rather than a gallery. */
.option-card-img {
  width: 100%;
  max-width: 100%;
  height: 120px;
  object-fit: var(--photo-fit);
  background: var(--photo-well-bg);
  display: block;
  /* THE 8px INSET GOES, same rule as the hero above. This is the FORM IMAGE the item's acceptance
     names, and it carried the fault in the same shape: an option photo that fills its square was
     drawn with a ring of well colour around it whether or not there was a gap to fill. */
}

/* A COLOUR SWATCH sits in the same slot a photo would, so a colour field and a photo field read as
   one system. Shorter than a photo because a flat colour needs no detail to be legible, and it
   carries its own border: a white or ivory swatch on a white card is otherwise invisible, which is
   the whole failure this element exists to avoid. */
.option-card-swatch {
  display: block;
  width: 100%;
  height: 64px;
  border-radius: 6px;
  border: 1px solid rgba(0, 0, 0, 0.18);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);
}

/* THE FRAME IS THE FIGURE, NOT ONLY THE IMAGE INSIDE IT (2026-09-16, "An image choice card's label
   overlaps the image when it runs to two lines"). In a stacked card the photo is wrapped in a
   .photo-figure, a flex item of the column card. Its height was taken from the photo's NATURAL size
   before the square frame applied, so on a phone the figure was 140px and the 322px square image
   drew out of it, straight over the label: measured on the canopy's LOCK FINISH at 390px, label top
   2192, image bottom 2374. At desktop widths the drawn square happened to be close to the natural
   size, which is why it looked like a two-line fault on some screens only.
   TRIED FIRST AND MEASURED NO CHANGE: flex-shrink: 0 on the image, and on the figure; flex: 0 0 auto
   with min-height: min-content. Only giving the FIGURE the frame's ratio is clean at 390, 900 and
   1440. The photo stays contained, never cropped: object-fit comes from the frame rule below. */
.option-card--stacked > .photo-figure {
  aspect-ratio: var(--photo-frame-ratio, 1);
  width: 100%;
  max-width: var(--photo-frame-max-w, 420px);
  flex-shrink: 0;
}

.option-card--stacked > .photo-figure > .option-card-img { height: 100%; }

/* .option-reference-image was RETIRED with render_as_reference (2026-07-22): the jack-off
   illustration now renders through the field-level image slot (.branch-image), so there is no
   option-anchored full-width reference class any more. */



.option-card--stacked .opt-label {
  padding: 8px 10px;
  font-size: 0.72rem;
  text-align: center;
  line-height: 1.3;
  white-space: pre-line;
  border-top: 1px solid var(--border-lt);
}
