@font-face {
  font-family: "Anton";
  src: url("/anton-subset.ttf") format("truetype");
  font-display: swap;
  font-weight: 400;
  font-style: normal;
}

:root { --bg:#fff; --fg:#000;
  /* ONE content column. The photo, the statement, the slider, the number field,
     the size bars, the buy button, the disclosure and the footer list all sit
     in it and agree on both edges at every viewport. Nothing below the header
     sets its own width or its own horizontal margin. */
  --col:20rem; --gutter:1rem; --col-box:calc(20rem + 2rem); }
* { box-sizing: border-box; }
body { margin:0; background:var(--bg); color:var(--fg);
       font:16px/1.4 -apple-system, "Helvetica Neue", Arial, sans-serif;
       font-stretch:condensed; }
a { color:var(--fg); }
header { padding:1rem; font-size:.9rem; text-transform:lowercase; }
main { max-width:40rem; margin:0 auto; padding:0 1rem 1rem; }
/* The shop pages (index, success). Policy pages keep the wider prose measure,
   so this is opt-in rather than a change to `main` itself. */
main.col { max-width:var(--col-box); padding:0 var(--gutter) 1rem; }
/* ONE garment view. #mockup is a real product photograph from the printer;
   #artwork is the print file alone inside a scale drawing of the print area,
   shown only when no photograph can be produced.
   No t-shirt is drawn anywhere in this stylesheet. */
#preview { margin:0; max-width:none; }
/* Both states occupy the same fixed-aspect box, and the box is sized before any
   image loads, so the frame never empties, never reflows, and the photo swap
   (a decoded image assigned to an already-laid-out element) shifts nothing. */
#preview-frame { position:relative; width:100%; aspect-ratio:1 / 1; }
#mockup { position:absolute; inset:0; width:100%; height:100%; object-fit:contain; }
[hidden] { display:none !important; }
#artwork { position:absolute; inset:0; display:flex; align-items:center;
  justify-content:center; border:1px solid #000; }
/* aspect-ratio is set per size by public/app.js from the real print area
   dimensions served by /api/print-geometry. Never hardcode it here. */
#print-area { position:relative; height:94%; outline:1px dashed #bbb; }
/* left/top/width are set per frame by app.js from the placement fractions that
   are sent to Printify; translate(-50%,-50%) makes them centre coordinates,
   matching CHEST_X/CHEST_Y. */
#art { position:absolute; transform:translate(-50%,-50%); }
#art svg { display:block; width:100%; height:auto; }
#statement { text-align:left; font-size:clamp(1rem,4.4vw,1.5rem); font-weight:700;
  letter-spacing:.02em; margin:.25rem 0 0; overflow-wrap:break-word; }
form { display:grid; gap:.75rem; max-width:none; margin:1rem 0 0; }
label { display:grid; gap:.25rem; font-size:.85rem; }
#price-slider-row { display:flex; align-items:center; gap:.5rem; }
#price-range { flex:1; accent-color:#000; }
/* Bare number field: no stepper chrome, fixed-width digits so the layout does
   not shift as the value changes while dragging. */
#price { width:5.5rem; flex:none; font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1; appearance:none; -moz-appearance:textfield; }
#price::-webkit-outer-spin-button,
#price::-webkit-inner-spin-button { -webkit-appearance:none; appearance:none; margin:0; }

/* Big drag readout. Fixed and pointer-events:none, so it can never shift the
   page or cover a control it would block. */
:root { --drag-fade:180ms; }
/* Narrow: across the top, clear of the slider and buttons lower down.
   Wide: out at the side, vertically centred, clear of the 40rem column. */
#drag-readout { position:fixed; left:0; right:0; top:0; text-align:center;
  background:var(--bg); padding:.25rem 0 .35rem;
  font-weight:800; font-size:clamp(2.5rem,13vw,4.5rem); line-height:1;
  font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1;
  color:#000; pointer-events:none; opacity:0; visibility:hidden;
  transition:opacity var(--drag-fade) ease-out, visibility 0s linear var(--drag-fade);
  z-index:10; }
#drag-readout.on { opacity:1; visibility:visible; transition:opacity 0s, visibility 0s; }
@media (min-width: 56rem) {
  #drag-readout { left:auto; right:3vw; top:50%; transform:translateY(-50%);
    text-align:right; font-size:clamp(4rem,9vw,9rem); background:none; padding:0; }
}
@media (prefers-reduced-motion: reduce) {
  #drag-readout { transition:none; }
}
/* app.js mirrors the same query onto <html> so the state object and the
   stylesheet can never disagree about it. */
.reduced-motion #drag-readout { transition:none; }
input, select, button { font:inherit; padding:.6rem; border:1px solid #000;
  background:#fff; color:#000; }
button { text-transform:lowercase; cursor:pointer; }
button:disabled { opacity:.4; cursor:not-allowed; }
/* One focus ring for the whole page, in the page's own ink rather than the
   browser default. */
input:focus-visible, button:focus-visible, a:focus-visible, summary:focus-visible {
  outline:2px solid #000; outline-offset:2px; }
#size-bars { display:flex; width:100%; }
.size-bar { flex:1; padding:.6rem 0; border:1px solid #000; background:#fff; color:#000;
  text-transform:lowercase; cursor:pointer; margin-left:-1px; }
.size-bar:first-child { margin-left:0; }
.size-bar[aria-checked="true"] { background:#000; color:#fff; }
/* Visually hidden but still in the accessibility tree, so aria-describedby and
   the live region resolve. Never display:none, which would remove them. */
.sr-only { position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap;
  border:0; }

/* --- buy button, and the one loading affordance on the page ---------------
   The garment image deliberately has none: it holds the last good photograph.
   This is the only place the page admits to waiting. */
#submit-row { position:relative; display:grid; }
#submit { display:flex; align-items:center; justify-content:center; gap:.5rem; }
#submit[aria-disabled="true"] { opacity:.55; cursor:progress; }
#submit-spinner { display:none; }
/* A plain monochrome ring with one open quadrant. No icon font, no SVG. */
#submit-row.updating #submit-spinner { display:block; width:.8em; height:.8em;
  border:2px solid currentColor; border-top-color:transparent; border-radius:50%;
  animation:submit-spin .8s linear infinite; }
@keyframes submit-spin { to { transform:rotate(360deg); } }
/* Reduced motion: keep the indicator, drop the rotation. */
@media (prefers-reduced-motion: reduce) {
  #submit-row.updating #submit-spinner { animation:none; border-top-color:currentColor;
    opacity:.45; }
}
.reduced-motion #submit-row.updating #submit-spinner { animation:none;
  border-top-color:currentColor; opacity:.45; }

/* Tooltip, on pointer hover AND keyboard focus, never hover-only. */
/* Below the button, not above: above would sit on top of the size bars. */
#submit-tip { position:absolute; top:calc(100% + .4rem); left:50%;
  transform:translateX(-50%); z-index:5; pointer-events:none;
  background:#000; color:#fff; font-size:.7rem; line-height:1;
  padding:.35rem .5rem; white-space:nowrap; opacity:0; visibility:hidden; }
#submit-row.updating #submit:hover ~ #submit-tip,
#submit-row.updating #submit:focus-visible ~ #submit-tip { opacity:1; visibility:visible; }

/* --- disclosure ----------------------------------------------------------
   Sits below the buy action and opens downward, so nothing above it moves. */
#detail { border-top:1px solid #000; margin-top:1.5rem; padding-top:.6rem; }
#detail > summary { cursor:pointer; font-size:.75rem; text-transform:lowercase;
  list-style:none; display:flex; align-items:center; gap:.4rem; padding:.15rem 0; }
#detail > summary::-webkit-details-marker { display:none; }
/* Explicit open/closed affordance drawn in CSS: a chevron that rotates. */
#detail > summary::before { content:""; width:.4rem; height:.4rem; flex:none;
  border-right:1.5px solid currentColor; border-bottom:1.5px solid currentColor;
  transform:rotate(-45deg); transform-origin:center; }
#detail[open] > summary::before { transform:rotate(45deg); }
#detail > summary:focus-visible { outline:2px solid #000; outline-offset:3px; }
#fit { font-size:.75rem; min-height:1.2em; margin:.5rem 0 .6rem; }
#breakdown { margin-top:0; }
/* Footer. A stacked list, aligned to the same optical column as the page body
   (main's 40rem measure), set well below the buy action so it reads as a
   separate region rather than more content. No rules, fills, bullets or icons:
   the separation is done with space and with a step down in weight. */
/* Same box as main.col, so the list's left and right edges land exactly on the
   size bars' at every width, including narrow, where both sit against the
   1rem gutter. */
footer { max-width:var(--col-box); margin:0 auto; padding:5rem var(--gutter) 4rem; }
footer ul { list-style:none; margin:0; padding:0; }
footer li { margin:0; }
footer a { display:inline-block; padding:.3rem 0; font-size:.75rem;
  line-height:1.35; letter-spacing:.01em; color:#555; text-decoration:none; }
footer a:hover { color:#000; text-decoration:underline; text-underline-offset:.2em; }
footer a:focus-visible { outline:2px solid #000; outline-offset:3px; color:#000; }
@media (min-width: 40rem) {
  footer { padding-top:6rem; }
}
.doc { max-width:34rem; margin:0 auto; padding:2rem 1rem 4rem; font-size:.9rem; }
.doc h1 { font-size:1rem; text-transform:lowercase; }
table.plain { border-collapse:collapse; width:100%; font-size:.85rem; }
table.plain td, table.plain th { border:1px solid #000; padding:.4rem .5rem; text-align:left; }
