/* ═══════════════════════════════════════════════════════════
   TOKENS
   ═══════════════════════════════════════════════════════════ */
:root{
  --paper:#F4EEDC;          /* page background — warm old-paper cream */
  --paper-2:#EFE7D2;        /* FAQ + footer, one step darker */
  --paper-3:#E7DDC3;        /* wells, placeholder */
  --ink:#1E1E1E;            /* primary text */
  --ink-2:#55524B;          /* secondary text */
  --white:#FFFFFF;
  --red:#C4322B;            /* sparingly: comic number, FAQ marginalia */
  --red-bright:#FF6A5E;     /* same accent on the black FAQ bar */
  --black:#151412;          /* FAQ header/footer bars */
  --line:rgba(30,30,30,.13);
  --line-2:rgba(30,30,30,.22);

  --display:"Barlow Condensed","Arial Narrow",system-ui,sans-serif;
  --body:"Inter",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  /* Margin notes only — the aside by Random and the FAQ marginalia. Never body
     copy. Handwriting runs small for its point size, hence the size bumps. */
  --hand:"Caveat","Segoe Script",cursive;

  --maxw:1420px;
  /* Both side columns — the comic rail on the left and the gear/FAQ column on
     the right — read from this, so the artwork sits centred between two equal
     margins instead of being pushed off-axis by a narrower rail. */
  --side:clamp(230px,21vw,320px);
  --gut:clamp(18px,3.6vw,54px);   /* page gutter; .shell repeats it literally */

  /* Ceiling for the artwork so a whole comic clears the fold on a laptop.
     The subtrahend is the chrome above it: header + the main grid's top
     padding + a little breathing room. svh (not vh) so mobile browser UI
     collapsing does not change the number mid-scroll. */
  --comic-max-h:calc(100svh - 200px);
}

*,*::before,*::after{box-sizing:border-box}
/* Always reserve the scrollbar's column. Without this a short page (a product
   page) has no scrollbar and a long one (the homepage) does, so the centred
   .shell recentres by half the scrollbar width and the whole page jumps
   sideways every time you click between them. */
html{-webkit-text-size-adjust:100%;scrollbar-gutter:stable}
/* Column flex + margin-top:auto on the footer keeps the sign-off strip pinned
   to the bottom of the viewport on short pages, so no cream ever shows under
   it. On long pages it just sits after the content as normal. */
body{
  margin:0;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--body);
  font-size:17px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
.site-footer{margin-top:auto}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0}
:focus-visible{outline:2.5px solid var(--red);outline-offset:3px;border-radius:3px}

/* Anything that also carries .shell must set padding-top/-bottom as LONGHANDS.
   The `padding` shorthand resets the horizontal sides to 0 and eats this gutter,
   which pins the logo to the left edge and clips the last nav item. */
.shell{
  /* width:100% matters: body is a column flex container, and an auto cross-axis
     margin cancels flex stretch — without it a .shell that is a direct flex
     child shrink-to-fits and sits narrower than the masthead. */
  width:100%;max-width:var(--maxw);margin:0 auto;
  padding-left:clamp(18px,3.6vw,54px);
  padding-right:clamp(18px,3.6vw,54px);
}

/* Visually hidden but read aloud. Lost when the CSS was extracted from the
   inline <style>, which made the search field's label render as visible text
   above its own placeholder. */
.vh{
  position:absolute;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
}

/* small zigzag flourish bracketing section labels */
/* Hand-drawn marks that bracket a section label. Sized per label rather than
   globally — Today's Comic carries them big, Share This Comic stays quiet. */
.mark{height:14px;width:auto;flex:none;display:block}
/* em-based so the marks track the label's clamped size instead of overflowing
   the rail and forcing the words onto two lines. */
.comic__label .mark{height:.82em}

/* generic stroked icon */
.ic{width:1em;height:1em;fill:none;stroke:currentColor;stroke-width:1.9;
    stroke-linecap:round;stroke-linejoin:round;flex:none}
.ic--fill{fill:currentColor;stroke:none}

/* ═══════════════════════════════════════════════════════════
   SiteHeader
   ═══════════════════════════════════════════════════════════ */
/* Masthead rule. Drawn as a pseudo-element inset to the gutters rather than a
   border on the header, so it stops at the content measure instead of bleeding
   to the window edges — and heavier, because a short rule is a deliberate mark
   and 1px at 13% just looks like a seam. */
.site-header{border-bottom:none}
.site-header__row{position:relative}
/* The masthead rule, deliberately heavier than every other line on the site.
   3px, not the 13% hairline used for separators — this one is part of the
   nameplate, and it is the only thing carrying weight in a cream header. */
.site-header__row::after{
  content:"";position:absolute;bottom:0;left:var(--gut);right:var(--gut);
  height:3px;background:var(--ink);
}
.site-header__row{
  display:flex;align-items:baseline;justify-content:space-between;
  flex-wrap:wrap;
  /* Split, not `gap`: once the row wraps, a single gap value also spaces the
     tagline 44px off the nameplate. Horizontal needs to be wide, vertical tight. */
  column-gap:clamp(20px,3vw,44px);
  row-gap:5px;
  padding-top:clamp(14px,2vw,24px);
  padding-bottom:clamp(10px,1.4vw,16px);
}
.brand__logo{
  font-family:var(--display);font-weight:900;
  font-size:clamp(34px,5.6vw,72px);
  line-height:.88;letter-spacing:-.004em;text-transform:uppercase;
  margin:0;
}
/* Its own full-width row under the nameplate, so it sits on the same measure
   as the masthead rule beneath it: nameplate, strapline, rule. */
.brand__tagline{
  width:100%;margin:2px 0 0;
  font-size:clamp(11.5px,1vw,13.5px);font-weight:600;
  line-height:1.5;letter-spacing:.035em;text-transform:uppercase;
  color:var(--ink-2);
}
.site-nav{display:flex;align-items:center;gap:clamp(12px,1.5vw,22px);padding-top:clamp(8px,1.6vw,20px)}
.site-nav a{
  font-weight:600;font-size:15px;letter-spacing:.055em;text-transform:uppercase;
  padding-bottom:5px;border-bottom:2.5px solid transparent;
}
.site-nav a:hover{border-bottom-color:var(--line-2)}
.site-nav a[aria-current="page"]{border-bottom-color:var(--ink)}

/* Nav and cart travel together on the right, so the flex row still resolves to
   brand | actions rather than spreading three items apart. */
.site-header__actions{display:flex;align-items:flex-end;gap:clamp(14px,1.8vw,26px)}
/* margin-bottom offsets the empty space under the wheels inside the icon's own
   viewBox, so the drawn cart sits on the nav text's baseline, not its box. */
.cart{
  position:relative;display:grid;place-items:center;
  width:42px;height:42px;font-size:28px;flex:none;margin-bottom:3.6px;
}
.cart:hover{opacity:.6}
/* Badge only when there is something in it — a permanent "0" is chrome people
   learn to ignore. Toggle by removing the `hidden` attribute. */
.cart__count{
  position:absolute;top:-1px;right:-3px;min-width:19px;height:19px;padding:0 5px;
  border-radius:999px;background:var(--red);color:var(--paper);
  font-size:11.5px;font-weight:700;line-height:19px;text-align:center;
}
.cart__count[hidden]{display:none}

.nav-toggle{display:none;padding:6px;margin:-6px;cursor:pointer;font-size:24px;line-height:1}

/* ═══════════════════════════════════════════════════════════
   Page grid — comic (≈70%) | FAQ (≈30%)
   ═══════════════════════════════════════════════════════════ */
.main{
  display:grid;
  grid-template-columns:minmax(0,1fr) var(--side);
  grid-template-areas:
    "comic gear"
    "comic faq"
    "shop  shop";
  grid-template-rows:auto 1fr auto;
  gap:clamp(28px,3vw,52px);
  align-items:start;
  padding-top:clamp(20px,2.4vw,32px);
  padding-bottom:clamp(40px,5vw,74px);
}

/* ═══════════════════════════════════════════════════════════
   ComicViewer
   ═══════════════════════════════════════════════════════════ */
/* Desktop puts Share in the text rail under the description, so nothing sits
   below the artwork at all. Rows are `auto 1fr` so the slack from the tall
   card lands in row 2 and Share stays tucked under the blurb. */
.comic{
  display:grid;
  grid-template-columns:var(--side) minmax(0,1fr);
  grid-template-areas:
    "rail  stage"
    "share stage"
    "prev  prev"
    "more  more"
    "join  join";
  grid-template-rows:auto 1fr auto auto auto;
  column-gap:clamp(28px,3vw,52px);   /* same as .main's gap, so the two sides match */
  row-gap:26px;
  align-items:start;
}
.comic__rail{grid-area:rail}
.comic__stage{grid-area:stage}
.comic-nav{grid-area:nav}
.share{grid-area:share}
.comic__label{
  display:flex;align-items:center;gap:5px;
  font-family:var(--display);font-weight:800;
  font-size:clamp(21px,1.85vw,26px);line-height:1;
  text-transform:uppercase;letter-spacing:.015em;
  white-space:nowrap;
  margin:0 0 18px;
}
.comic__meta{
  font-size:14px;font-weight:500;letter-spacing:.05em;text-transform:uppercase;
  color:var(--red);margin:0 0 6px;
}
.comic__title{
  font-family:var(--display);font-weight:800;
  font-size:clamp(30px,3.1vw,42px);line-height:.98;
  text-transform:uppercase;letter-spacing:-.002em;
  margin:0 0 14px;
}
.comic__blurb{margin:0;color:var(--ink-2);font-size:16.5px;line-height:1.55}
/* Drawn as a margin annotation: the arrow curls up toward the Random button
   with the note tucked into its elbow, two lines, the way it is in the mockup. */
/* Drawn as a margin annotation: the arrow curls up toward the Random button
   with the note written underneath it, the way it is in the mockup. */
.comic__aside{
  /* Full ink, not --ink-2: this is the call to action, and in secondary grey it
     read as a continuation of the blurb above rather than something to do. */
  margin:0 0 11px;font-family:var(--hand);font-weight:600;font-size:24px;
  color:var(--ink);line-height:1.08;
  display:flex;flex-direction:column;align-items:flex-start;text-align:left;gap:3px;
}
.aside__art{height:40px;width:auto;flex:none}

/* Artwork and its controls share a column so PREV/RANDOM/NEXT and the share
   row line up under the comic rather than centring across rail + comic. */
/* Prev/Next flank the card on desktop. The stage reserves a lane on each side
   via padding, so the arrows sit strictly OUTSIDE the artwork — never over it —
   and the card shrinks to respect the lanes rather than sliding under them. */
.comic__stage{
  position:relative;
  width:fit-content;max-width:100%;margin-inline:auto;
  padding-inline:48px;
}
.comic__arrow{
  position:absolute;top:50%;transform:translateY(-50%);
  width:40px;height:40px;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;
  background:transparent;color:var(--ink);
  border:1.5px solid var(--line-2);
  transition:background .15s,color .15s,border-color .15s;
}
.comic__arrow:hover:not(:disabled){background:var(--ink);color:var(--paper);border-color:var(--ink)}
/* Dimmed at the ends of the run rather than looking clickable and doing
   nothing — same treatment as the strip arrows below. */
.comic__arrow:disabled{opacity:.26;cursor:default}
.comic__arrow .ic{font-size:19px;stroke-width:2.1}
.comic__arrow--prev{left:0}
.comic__arrow--next{right:0}
/* The figure shrink-wraps the artwork, so capping the image by height leaves
   no letterbox bars inside the frame — the frame shrinks with it. */
.comic__figure{
  margin:0 auto;width:fit-content;max-width:100%;
  border:1px solid var(--line);
  background:var(--paper-3);overflow:hidden;
  box-shadow:0 8px 28px rgba(30,30,30,.10);
}
/* ratio is whatever the file is — never cropped, never stretched */
.comic__img{
  width:auto;height:auto;
  max-width:100%;max-height:var(--comic-max-h);
  object-fit:contain;
}
/* 5:7 is the artwork's true ratio (1060x1484 — trading-card proportions), so
   the empty state reserves exactly the box the loaded comic will occupy. */
.comic__figure.is-empty{
  height:var(--comic-max-h);aspect-ratio:5/7;
  display:grid;place-items:center;text-align:center;
}
.comic__figure.is-empty .comic__img{display:none}
.comic__figure.is-empty::after{
  content:"COMIC ARTWORK";
  font-family:var(--display);font-weight:800;font-size:19px;
  letter-spacing:.14em;color:var(--ink-2);opacity:.5;
}

/* ── ComicNavigation ── */
.comic-nav{
  display:flex;align-items:center;justify-content:center;
  gap:clamp(9px,1.3vw,16px);flex-wrap:wrap;
}
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-weight:700;font-size:13.5px;letter-spacing:.07em;text-transform:uppercase;
  padding:12px 20px;border-radius:8px;
  border:1.5px solid var(--line-2);background:transparent;cursor:pointer;
  transition:background .15s,color .15s,border-color .15s;
}
.btn:hover{border-color:var(--ink)}
.btn--solid{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.btn--solid:hover{background:#000}
/* "Previous" where there is room, "Prev" on phones — otherwise the three
   comic controls wrap onto two rows below ~420px. */
.btn__short{display:none}

/* One Random control, never two. On desktop it sits in the rail beside the
   artwork; once the rail stacks it moves inline between Prev and Next. */
.comic-nav__random{display:none}

/* ── ShareControls ── */
.share{text-align:center}
.share__label{
  display:inline-flex;align-items:center;gap:5px;
  font-family:var(--display);font-weight:700;font-size:16px;
  letter-spacing:.09em;text-transform:uppercase;color:var(--ink-2);
}
.share__list{
  display:flex;justify-content:center;align-items:center;flex-wrap:wrap;
  gap:clamp(16px,2.4vw,30px);margin-top:0;
}
.share__list a{display:grid;place-items:center;width:34px;height:34px;font-size:24px;color:var(--ink)}
.share__list a:hover{opacity:.6}

/* ═══════════════════════════════════════════════════════════
   FAQSidebar
   ═══════════════════════════════════════════════════════════ */
/* Deliberately NOT sticky. A sticky item is bounded by its parent's content
   box (.main), not its grid row, so it slid down over the full-width group
   banner beneath. The panel is nearly viewport-height anyway — sticky bought
   ~80px of travel and cost an overlap. */
/* Heading follows the same system as every other section — marks plus display
   type on cream — instead of the black slab, which was the one heading on the
   site that looked borrowed from a different design. The panel keeps its border
   and tint; only the header moved out of it. */
.faq{border:0;background:none}
.faq__head{
  margin:0 0 12px;display:flex;align-items:baseline;justify-content:space-between;
  gap:14px;flex-wrap:wrap;
}
.faq__head .comic__label{margin:0}
.faq__body{
  border:1px solid var(--line-2);overflow:hidden;
  background:var(--paper-2);
}
/* The bubble's tail hangs below its body, so centring the FILE leaves the round
   part reading high. Its body centre measures 11.3% of the height above centre;
   shift by that so the bubble optically centres against the FAQ wordmark. */
/* line-height:1 centres the BOX, not the letters — the caps sit ~4% low because
   the box reserves descender space this all-caps wordmark barely uses. Shift by
   the measured cap-height offset so FAQ optically centres against the bubble. */
/* Red on cream now, not the brighter value that was tuned for the black bar. */
.faq__note{
  margin:0;color:var(--red);
  font-family:var(--hand);font-weight:700;font-size:17px;line-height:1.15;
}
/* Rules inset to the text's left edge and running out to the panel's right —
   a border can't be inset, so it's a pseudo-element. `+` means the first item
   never gets one. */
.faq__item{position:relative}
.faq__item + .faq__item::before{
  content:"";position:absolute;top:0;left:17px;right:0;height:1px;
  background:var(--line);
}
.faq__q{
  margin:0;padding:15px 17px 5px;
  font-weight:700;font-size:15.5px;line-height:1.4;
}
.faq__item:first-of-type .faq__q{padding-top:15px}
.faq__a{margin:0;padding:0 17px 15px;color:var(--ink-2);font-size:15px;line-height:1.55}

/* ═══════════════════════════════════════════════════════════
   SiteFooter
   ═══════════════════════════════════════════════════════════ */
/* One dark block, not a cream band with a black strip stuck under it: at 2%
   darker than the page the cream read as more page, which left the sign-off
   strip looking orphaned. Padding belongs to the inner row, not the footer,
   or it also sits below the strip. */
.site-footer{background:var(--black);color:var(--paper)}
.site-footer__top{
  padding-top:clamp(26px,3.2vw,42px);
  padding-bottom:clamp(14px,1.6vw,20px);
}
.site-footer__row{display:flex;align-items:center;justify-content:space-between;gap:22px;flex-wrap:wrap}
.site-footer__logo{margin:0;font-family:var(--display);font-weight:900;font-size:clamp(24px,2.6vw,34px);line-height:1;text-transform:uppercase}
.site-footer__nav{display:flex;gap:clamp(18px,2.4vw,30px)}
.site-footer__nav a{font-weight:600;font-size:14px;letter-spacing:.055em;text-transform:uppercase}
.site-footer__nav a:hover{text-decoration:underline;text-underline-offset:4px}
.site-footer__copy{width:100%;margin:18px 0 0;font-size:13px;color:rgba(244,238,220,.6)}

/* ═══════════════════════════════════════════════════════════
   RESPONSIVE — one page, no separate mobile build
   ═══════════════════════════════════════════════════════════ */
@media (max-width:1140px){
  .main{
    grid-template-columns:1fr;
    grid-template-areas:"comic" "gear" "faq" "shop";
    grid-template-rows:auto auto auto auto;
  }
}
@media (max-width:900px){
  .comic{
    grid-template-columns:1fr;
    grid-template-areas:"rail" "stage" "nav" "share" "prev" "more" "join";
    grid-template-rows:auto auto auto auto auto;
  }
  .comic-nav{grid-area:nav}
  /* Phones stack the number, title and blurb above the artwork, so the fold is
     already spent by the time we get here. Stay immersive instead: full width,
     with a generous ceiling only so a very tall scan cannot run away. */
  :root{--comic-max-h:85svh}
  .comic__figure{width:92%}
  .comic__img{width:100%}
  .comic__rail{text-align:center}
  .comic__label{justify-content:center}
  .comic__aside{justify-content:center}
  .comic__arrow{display:none}
  .comic__aside{align-items:center;text-align:center}
  .comic__stage{padding-inline:0}
  .comic-nav__random{display:inline-flex}
}
/* Desktop stacks every control in the rail under the blurb — Random, then
   Prev/Next, then Share — so the artwork carries nothing and nothing follows
   it. Buttons and icons shrink to fit the rail rather than wrapping. */
@media (min-width:901px){
  .comic-nav{display:none}
  /* A hairline separates the comic's description from the things you can do
     about it — without it the whole rail reads as one block of prose. */
  .share{text-align:left;border-top:1px solid var(--line);padding-top:20px}
  /* 6 x 28 + 5 x 8 = 208 in a 215px rail. Any larger and the sixth icon wraps
     to a second row, so grow the glyph inside the box, not the box. */
  .share__list{justify-content:flex-start;gap:8px;margin-top:11px}
  .share__list a{width:28px;height:28px;font-size:22px}
}
@media (max-width:860px){
  .site-header__row{
    display:grid;grid-template-columns:32px 1fr 32px;align-items:center;
    justify-items:center;gap:12px;
  }
  .nav-toggle{display:block;justify-self:start;grid-column:1}
  .brand{grid-column:2;text-align:center}
  /* display:contents lets nav and cart be placed as grid items directly */
  .site-header__actions{display:contents}
  .cart{grid-column:3;justify-self:end}
  .brand__tagline{grid-column:1/-1;margin-inline:auto;text-align:center;max-width:34ch}
  .site-nav{
    grid-column:1/-1;display:none;width:100%;
    flex-direction:column;align-items:center;gap:2px;
    padding:8px 0 4px;border-top:1px solid var(--line);
  }
  .site-nav.is-open{display:flex}
  .site-nav a{padding:11px 0;width:100%;text-align:center;border-bottom:0}
  .site-nav a[aria-current="page"]{color:var(--red)}
}
@media (max-width:560px){
  body{font-size:16px}
  .btn{padding:11px 12px;font-size:12.5px;gap:7px}
  .btn__full{display:none}
  .btn__short{display:inline}
  .comic-nav{gap:8px}
  .faq__note{display:none}
  .site-footer__row{flex-direction:column;align-items:flex-start;gap:16px}
}
@media (prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important}
}

/* ═══════════════════════════════════════════════════════════
   JoinGroup — sits below the fold on purpose. Someone who
   scrolled past the comic is the only one worth asking.
   ═══════════════════════════════════════════════════════════ */
.join{
  grid-area:join;
  display:flex;align-items:center;gap:clamp(14px,2vw,26px);flex-wrap:wrap;
  /* Open, not boxed: the old container was --paper-2 on --paper, a ~2% tint
     doing no work, and the solid button already reads as actionable. A rule
     separates it, matching how the share block is handled. */
  margin-top:clamp(6px,1.4vw,16px);
  border-top:1px solid var(--line);
  padding:clamp(20px,2.4vw,28px) 0 0;
  cursor:pointer;
}
/* The whole banner is the link, so hovering anywhere in it has to respond —
   otherwise the hit area is invisible and only the button looks live. */
.join:hover .join__title{text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:2px}
.join:hover .btn{background:#000}
.join:focus-visible{outline-offset:6px}
.join__text{flex:1;min-width:210px}
.join__title{
  margin:0;font-family:var(--display);font-weight:800;
  font-size:clamp(22px,2.2vw,28px);line-height:1;
  text-transform:uppercase;letter-spacing:.01em;
}
.join__body{margin:8px 0 0;color:var(--ink-2);font-size:15px;line-height:1.5}
.join .btn{flex:none}
@media (max-width:560px){
  .join{flex-direction:column;align-items:stretch;text-align:center}
  .join .btn{width:100%}
}

/* ═══════════════════════════════════════════════════════
   Calendar - one comic a day, so the calendar IS the index. Days with no
   comic stay visible but dead, which reads as "not yet" rather than a gap.
   ═══════════════════════════════════════════════════════ */
/* The cadence, stated rather than counted down. A countdown has to be right 365
   times a year and sits at 00:00:00 announcing the miss on the day it isn't;
   this can only ever be a day stale. It sits with the dateline because that is
   where "when" already lives on this page. */
.comic__next{
  margin:2px 0 12px;font-size:13px;font-weight:500;
  letter-spacing:.03em;color:var(--ink-2);
}
.metarow{position:relative;display:flex;align-items:center;gap:8px;margin-bottom:6px}
.metarow .comic__meta{margin:0}
/* Labelled, not just an icon: a bare calendar glyph is the one control on this
   page nobody can name without clicking it. Borrows the gear buttons' outline
   and invert-on-hover so the site has one button shape, not two. */
.cal-btn{
  display:flex;align-items:center;gap:6px;flex:none;
  height:26px;padding:0 9px 0 7px;
  border:1.5px solid var(--line-2);border-radius:8px;
  cursor:pointer;color:var(--ink-2);font-size:15px;
  transition:background .15s,color .15s,border-color .15s;
}
/* Inverts on hover, same as the gear buttons. The open state holds the invert
   so it stays obviously "on" while the calendar is showing. */
.cal-btn:hover,.cal-btn[aria-expanded="true"]{
  background:var(--ink);color:var(--paper);border-color:var(--ink);
}
.cal{
  position:absolute;z-index:30;top:calc(100% + 9px);left:0;width:252px;
  background:var(--paper);border:1px solid var(--line-2);border-radius:11px;
  box-shadow:0 14px 34px rgba(30,30,30,.17);
  padding:11px 12px 13px;text-align:left;
}
.cal__head{display:flex;align-items:center;justify-content:space-between;gap:6px;padding-bottom:9px}
.cal__title{
  font-family:var(--display);font-weight:800;font-size:17px;
  text-transform:uppercase;letter-spacing:.02em;
}
.cal__nav{
  display:grid;place-items:center;width:26px;height:26px;flex:none;
  border-radius:6px;cursor:pointer;color:var(--ink-2);font-size:15px;
}
.cal__nav:hover{background:var(--paper-3);color:var(--ink)}
.cal__nav[disabled]{opacity:.28;cursor:default;background:none}
.cal__dow,.cal__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.cal__dow span{
  text-align:center;font-size:10.5px;font-weight:600;color:var(--ink-2);
  opacity:.65;padding-bottom:4px;letter-spacing:.04em;
}
.cal__day{
  height:30px;border-radius:7px;font-size:12.5px;font-weight:500;
  display:grid;place-items:center;color:var(--ink-2);
}
.cal__day--empty{visibility:hidden}
.cal__day--none{opacity:.3}
.cal__day--has{color:var(--ink);font-weight:600;cursor:pointer}
/* :not(--on) matters. A plain :hover outranks .cal__day--on, so hovering the
   selected day replaced its dark background while keeping its light text —
   pale text on a pale tint, unreadable. */
.cal__day--has:hover:not(.cal__day--on){background:var(--paper-3);color:var(--ink)}
.cal__day--on{background:var(--ink);color:var(--paper)}
@media (max-width:900px){
  .metarow{justify-content:center}
  .cal{left:50%;transform:translateX(-50%)}
}

/* Supplied artwork standing in for the drawn icons. */
.btn__art{height:30px;width:auto;flex:none;margin:-4px 0}
.foot__art{height:54px;width:auto;flex:none}
.join__art{height:92px;width:auto;flex:none}
@media (max-width:560px){
  .join__art{height:74px;align-self:center}
}

/* Sign-off strip. Lives at page width, not in the FAQ column — the line is 51
   characters and wrapped to three in a 380px panel. */
.site-footer__barrow{
  /* `margin:0` here would cancel .shell's `margin:0 auto` and stop this row
     centring, so above 1420px it would drift left of every other row. */
  margin:0 auto;display:flex;align-items:center;gap:13px;
  padding-top:6px;padding-bottom:26px;
  font-size:13px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;
}
@media (max-width:560px){
  .site-footer__barrow{font-size:12px;gap:10px}
  .foot__art{height:32px}
}

/* Random lives inside the calendar: both are "show me a different comic",
   and one browse surface beats a heavy button competing with Share. */
.cal__random{
  width:100%;margin-top:11px;
  display:flex;align-items:center;justify-content:center;gap:8px;
  padding:10px 12px;border-radius:8px;cursor:pointer;
  background:var(--ink);color:var(--paper);
  font-weight:700;font-size:12px;letter-spacing:.07em;text-transform:uppercase;
}
.cal__random:hover{background:#000}
.cal__random img{height:22px;width:auto;flex:none;margin:-4px 0}


/* Spans both columns: five tiles need the full measure, and the space under
   the FAQ was otherwise dead. Sells the OTHER designs — the rail's gear module
   sells the one currently on screen. */
.shop{
  grid-column:1/-1;
  margin-top:8px;padding-top:20px;
  border-top:1px solid var(--line);
}

/* Shop row. Product tiles are square with the artwork CONTAINED, not cropped —
   a shirt print sits on the tile the way it would on the garment, and nothing
   introduces a second colour source beyond the art itself. */
.shop__head{
  margin:0 0 14px;display:flex;align-items:baseline;justify-content:space-between;gap:16px;
}
.shop__label{
  font-family:var(--display);font-weight:800;font-size:22px;line-height:1;
  text-transform:uppercase;letter-spacing:.015em;
}
.shop__all{
  font-weight:700;font-size:12.5px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink-2);
}
.shop__all:hover{color:var(--ink)}
.shop__grid{
  display:grid;grid-template-columns:repeat(5,1fr);
  gap:clamp(14px,1.8vw,24px);
}
.shopcard{display:flex;flex-direction:column;gap:11px;cursor:pointer}
/* Full artwork at its own 5:7, not cropped square. A theme IS the comic, so
   squaring it cuts the joke — the same reason the comic viewer never crops. */
.shopcard__tile{display:block;aspect-ratio:5/7;overflow:hidden}
.shopcard__tile img{width:100%;height:100%;object-fit:contain;display:block}
.shopcard__name{
  font-family:var(--display);font-weight:800;font-size:20px;line-height:1.05;
  text-transform:uppercase;letter-spacing:.01em;
}
.shopcard__meta{font-size:13.5px;color:var(--ink-2);margin-top:-6px}
.shopcard:hover .shopcard__name{text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:2px}
@media (max-width:900px){
  .shop__grid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr))}
}
/* Phones: one product at a time, swiped. Stacking five vertically adds a lot of
   scroll to an already long page. The card is 78% wide so the next one peeks —
   without that edge showing, nobody knows the row scrolls. Negative margin lets
   it bleed past the page gutter so the peek reaches the screen edge. */
@media (max-width:640px){
  .shop__grid{
    display:flex;grid-template-columns:none;gap:12px;
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;
    scroll-padding-left:var(--gut);
    padding-inline:var(--gut);
    margin-inline:calc(-1 * var(--gut));
    scrollbar-width:none;
  }
  .shop__grid::-webkit-scrollbar{display:none}
  .shopcard{flex:0 0 78%;scroll-snap-align:start}
}
@media (max-width:560px){
  .shop__grid{gap:12px}
  .shopcard__name{font-size:16px}
  .shopcard__meta{font-size:12.5px}
}

/* ═══════════════════════════════════════════════════════════
   About page
   ═══════════════════════════════════════════════════════════ */
.about{
  display:block;
  /* same clearance under the masthead rule as .main on the homepage */
  padding-top:clamp(20px,2.4vw,32px);
  padding-bottom:clamp(40px,5vw,74px);
  /* One measure for every text block, so all right edges land together.
     Only the tally and the section labels run full width. */
  --measure:860px;
}
.about > section + section{margin-top:clamp(38px,4.5vw,66px)}

.about__lede{
  display:grid;grid-template-columns:minmax(0,var(--measure)) minmax(200px,1fr);
  gap:clamp(24px,3.4vw,56px);align-items:start;
}
/* Page titles all share one size — About, Shop and Checkout were at 84, 64 and
   52 for no reason anyone could have named. Leading stays tighter here because
   this is the only one that runs to two lines, which is a function of line
   count, not of hierarchy. */
.about__title{
  margin:0 0 18px;font-family:var(--display);font-weight:900;
  font-size:clamp(38px,5vw,64px);line-height:.92;
  text-transform:uppercase;letter-spacing:-.005em;
}
.about__intro{margin:0 0 14px;font-size:clamp(17px,1.4vw,19.5px);line-height:1.6}
.about__intro strong{font-weight:600}
.about__portrait{margin:0}
.about__portrait img{width:100%;height:auto;border:1px solid var(--line)}
.about__portrait figcaption{margin-top:9px;font-size:12.5px;color:var(--ink-2);line-height:1.45}
.about__portrait code{font-family:ui-monospace,"SF Mono",monospace;font-size:11.5px}
.about__portrait.is-empty img{display:none}
.about__portrait.is-empty::before{
  content:"PORTRAIT";display:grid;place-items:center;aspect-ratio:4/5;
  background:var(--paper-3);border:1px solid var(--line);
  font-family:var(--display);font-weight:800;font-size:17px;
  letter-spacing:.14em;color:var(--ink-2);opacity:.5;
}

/* The joke is the fourth and fifth numbers landing after the first three. */
.tally{
  display:grid;grid-template-columns:repeat(5,1fr);
  background:var(--black);color:var(--paper);
}
.tally div{padding:clamp(18px,2.2vw,26px) clamp(12px,1.6vw,20px)}
.tally div + div{border-left:1px solid rgba(244,238,220,.14)}
.tally__n{
  display:block;font-family:var(--display);font-weight:900;
  font-size:clamp(34px,4vw,54px);line-height:1;
}
.tally__l{
  display:block;margin-top:6px;font-size:12px;font-weight:600;
  letter-spacing:.05em;text-transform:uppercase;color:rgba(244,238,220,.62);
}

.beats{list-style:none;margin:0;padding:0;max-width:var(--measure)}
.beats li{display:grid;grid-template-columns:88px minmax(0,1fr);gap:clamp(14px,2vw,26px);padding:16px 0}
.beats li + li{border-top:1px solid var(--line)}
.beats__when{
  font-family:var(--display);font-weight:800;font-size:19px;line-height:1.3;
  text-transform:uppercase;letter-spacing:.04em;color:var(--red);
}
.beats p{margin:0;font-size:16.5px;line-height:1.6;color:var(--ink-2)}
.beats strong{color:var(--ink);font-weight:600}

.about__nextgrid{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(20px,2.6vw,40px);max-width:var(--measure);
}
.about__h3{
  margin:0 0 7px;font-family:var(--display);font-weight:800;font-size:24px;
  line-height:1;text-transform:uppercase;
}
.about__nextgrid p{margin:0;color:var(--ink-2);font-size:16.5px;line-height:1.6}
.about__next .btn{margin-top:22px}

.about__contactgrid{
  margin:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(14px,2vw,28px);max-width:var(--measure);
}
.about__contactgrid a{
  display:block;padding-top:14px;border-top:1px solid var(--line);
  font-size:16.5px;line-height:1.5;
}
.about__contactgrid a strong{font-weight:600}
.about__contactgrid a span{color:var(--ink-2);font-size:14px}
.about__contactgrid a:hover strong{text-decoration:underline;text-underline-offset:4px}

@media (max-width:900px){
  .about__lede{grid-template-columns:1fr}
  .about__portrait{max-width:300px}
  .tally{grid-template-columns:repeat(2,1fr)}
  .tally div{border-left:0;border-top:1px solid rgba(244,238,220,.14)}
  .tally div:nth-child(odd){border-right:1px solid rgba(244,238,220,.14)}
  .tally div:nth-child(-n+2){border-top:0}
  .about__nextgrid,.about__contactgrid{grid-template-columns:1fr}
  .beats li{grid-template-columns:1fr;gap:4px}
}

/* ═══════════════════════════════════════════════════════════
   Shop page
   ═══════════════════════════════════════════════════════════ */
.shoppage{
  display:block;
  padding-top:clamp(20px,2.4vw,32px);
  padding-bottom:clamp(40px,5vw,74px);
}
.shoppage__head{
  display:flex;align-items:baseline;justify-content:space-between;
  gap:20px;flex-wrap:wrap;
}
.shoppage__title{
  margin:0;font-family:var(--display);font-weight:900;
  font-size:clamp(38px,5vw,64px);line-height:.95;text-transform:uppercase;
}
.shoppage__note{margin:0;color:var(--ink-2);font-size:16.5px}

/* Filters are text, not pills — a catalogue this size does not need chrome. */
.filters{
  display:flex;align-items:center;gap:clamp(14px,2vw,26px);flex-wrap:wrap;
  margin-top:clamp(18px,2.2vw,26px);padding-bottom:14px;
  border-bottom:2px solid var(--ink);
}
/* Pills, not underlines. The view menu above already uses an underline, and so
   does the site nav for the current page — three levels sharing one treatment
   made them read as peers. Underline = which view. Pill = filter within it. */
.filters__btn{
  cursor:pointer;padding:6px 13px;border-radius:999px;
  border:1.5px solid var(--line-2);
  font-weight:700;font-size:12.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-2);
  transition:background .15s,color .15s,border-color .15s;
}
.filters__btn:hover{color:var(--ink);border-color:var(--ink)}
.filters__btn.is-on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
/* Controls group on the left, the result sits alone on the right. Only one
   auto margin on this row — two split the free space and float things mid-row. */
.filters__count{
  margin-left:auto;font-size:13px;color:var(--ink-2);
  letter-spacing:.04em;text-transform:uppercase;
}

/* Fixed 4 columns so every row's edges line up with the filter rule above and
   the footer below — auto-fill would leave a ragged gap on the last row. */
.shoppage__grid{
  grid-template-columns:repeat(4,1fr);
  margin-top:clamp(26px,3vw,40px);
  /* Rows are spaced wider than columns on purpose. The caption sits 11px under
     its own artwork, so an equal row gap would leave it floating halfway
     between its image and the one below — reading as a caption for neither. */
  column-gap:clamp(16px,1.9vw,26px);
  row-gap:clamp(32px,3.6vw,52px);
}
.shopcard[hidden]{display:none}

@media (max-width:1100px){ .shoppage__grid{grid-template-columns:repeat(3,1fr)} }
@media (max-width:760px){  .shoppage__grid{grid-template-columns:repeat(2,1fr)} }
@media (max-width:420px){
  .shoppage__grid{grid-template-columns:1fr}
  .filters__count{margin-left:0;width:100%}
}

/* ═══════════════════════════════════════════════════════════
   Gear — merch for the comic currently on screen
   Lives above the FAQ in the right column: it is the only arrangement where
   share AND gear both clear the fold, because the left rail no longer has to
   carry both. The artwork is already large alongside, so this never repeats it.
   Nobody merchandises it — the comic changes, the offer changes.
   ═══════════════════════════════════════════════════════════ */
.gear{grid-area:gear}
.gear__head{
  margin:0 0 6px;display:flex;align-items:baseline;justify-content:space-between;
  gap:14px;flex-wrap:wrap;
}
.gear__head .comic__label{margin:0}
.gear__note{
  margin:0 0 12px;font-family:var(--hand);font-weight:600;font-size:21px;
  line-height:1.08;color:var(--ink);
}
.gear__opts{display:grid;grid-template-columns:repeat(3,1fr);gap:9px}
.gear__opts a{
  display:flex;flex-direction:column;align-items:center;gap:3px;
  padding:12px 6px;border:1.5px solid var(--line-2);border-radius:8px;
  transition:background .15s,color .15s,border-color .15s;
}
.gear__opts a:hover{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.gear__opts span{
  font-family:var(--display);font-weight:800;font-size:18px;line-height:1;
  text-transform:uppercase;letter-spacing:.02em;
}
.gear__opts b{font-size:13.5px;font-weight:600}
.gear__all{
  font-weight:700;font-size:12.5px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink-2);
}
.gear__all:hover{color:var(--ink)}

.comic{grid-area:comic}
.faq{grid-area:faq}
.shop{grid-area:shop}

/* "From" prefix for products whose price varies by size. Deliberately small and
   quiet — it qualifies the number without competing with it. Add or remove per
   item by wrapping the word in <i>; nothing else changes. */
.gear__opts b i,
.shopcard__meta i{
  font-style:normal;font-size:.72em;font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;opacity:.65;
  margin-right:2px;
}

/* The gear heading names the comic on screen, so unlike the other labels it has
   to survive a long title: wrapping allowed, and it tracks .comic__title. */
.gear__label{white-space:normal;line-height:1.02}

/* Search sits with the filters — at 200 designs people recall the picture, not
   the title, so it matches tags too. */
/* The most useful control at 200 themes, so it should not read as a caption:
   glyph, wider, and a rule heavy enough to look like a field. */
.filters__search{
  flex:0 1 320px;min-width:190px;
  display:flex;align-items:center;gap:8px;
  padding-bottom:7px;border-bottom:2px solid var(--line-2);
}
.filters__search:focus-within{border-bottom-color:var(--ink)}
.filters__search .ic{font-size:17px;color:var(--ink-2);flex:none}
.filters__search:focus-within .ic{color:var(--ink)}
.filters__search input{
  width:100%;font:inherit;font-size:15px;
  padding:0;border:0;background:none;color:var(--ink);
}
.filters__search input::placeholder{color:var(--ink-2);opacity:.75}
.filters__search input:focus{outline:none}
.shop__empty{
  margin:40px 0;text-align:center;color:var(--ink-2);
  font-family:var(--hand);font-size:22px;
}
.shop__empty[hidden]{display:none}

/* Wordmark goes home from every page — the one navigation convention people
   try without being told. */
.brand__logo a{display:inline-block}
.brand__logo a:hover{opacity:.72}

/* Shop view menu: Products or Themes. Two doors into one catalogue — pick the
   thing you want to own, or pick the comic you liked. */
/* Tighter than the gap to the SHOP title, so the two read as one toggle rather
   than as two more items in a row with the heading. */
.views{display:flex;gap:12px;margin-top:clamp(16px,2vw,24px)}
.views__btn{
  cursor:pointer;padding:2px 0;
  font-family:var(--display);font-weight:800;font-size:22px;line-height:1;
  text-transform:uppercase;letter-spacing:.02em;
  color:var(--ink-2);border-bottom:2.5px solid transparent;
}
.views__btn:hover{color:var(--ink)}
.views__btn.is-on{color:var(--ink);border-bottom-color:var(--ink)}

/* ═══════════════════════════════════════════════════════════
   Theme page — one comic, everything it comes on
   ═══════════════════════════════════════════════════════════ */
.themepage{display:block;padding-top:clamp(20px,2.4vw,32px);padding-bottom:clamp(40px,5vw,74px)}
/* Breadcrumbs, not a back link. A single "back" arrow can only guess where you
   came from; a trail reaches the homepage, the whole shop and the design at
   once, and Google renders it in place of the raw URL in a result. */
.crumbs{
  display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  margin:0 0 26px;font-weight:700;font-size:13.5px;
  letter-spacing:.05em;text-transform:uppercase;color:var(--ink-2);
}
.crumbs a{display:inline-flex;align-items:center;gap:6px;padding:5px 0}
.crumbs a:hover{color:var(--ink)}
.crumbs [aria-current]{color:var(--ink)}
/* Separator drawn rather than typed, so it cannot be selected or read aloud. */
.crumbs a::after{content:"";width:5px;height:5px;border-radius:50%;background:var(--line-2)}
.crumbs a:last-of-type::after{display:none}
.crumbs__back{font-size:17px;stroke-width:2.2}

.themepage__back{margin:0 0 26px;font-weight:700;font-size:16px;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-2)}
/* One text node holds arrow and label together (JS rewrites it wholesale to
   match where you came from), so the whole link scales rather than the arrow. */
.themepage__back a{display:inline-block;padding:5px 0}
.themepage__back a:hover{color:var(--ink)}
/* The art track hugs the artwork rather than taking a 1fr share. A 5:7 image
   capped by height can never fill a wide track — it was leaving a 333px hole
   between the art and the buy column. The buy column absorbs the slack instead,
   up to a width where the detail copy still reads at a sane line length. */
.themepage__grid{
  display:grid;
  /* The buy column scales rather than claiming a flat 520px — at a fixed max it
     won the space fight on mid-size screens and squeezed the art down to 249px. */
  grid-template-columns:minmax(0,auto) clamp(320px,34vw,520px);
  justify-content:start;
  gap:clamp(30px,3.6vw,62px);
  align-items:start;
}
/* Shrink-wrap the figure to the art. A grid item stretches by default, so the
   panel ran wider than the 5:7 image and showed cream bars down both sides. */
.themepage__art{margin:0;justify-self:start;border:1px solid var(--line);background:var(--paper-3)}
.themepage__art img{
  display:block;width:auto;height:auto;
  max-height:calc(100svh - 220px);
  /* Ratio is fixed at 5:7, so the height cap implies a width cap. Stating it
     keeps the figure's max-content size bounded — without it an `auto` track
     resolves against the image's natural 1060px and the layout blows out. */
  max-width:min(100%, calc((100svh - 220px) * 5 / 7));
}
.themepage__title{margin:0 0 12px;font-family:var(--display);font-weight:800;font-size:clamp(30px,3.4vw,46px);line-height:1;text-transform:uppercase}
.themepage__dek{margin:0 0 26px}
.themepage__note{margin:0 0 26px;font-family:var(--hand);font-weight:600;font-size:22px;color:var(--ink)}
.theme__opts{display:grid;gap:11px}
.theme__opt{display:flex;align-items:baseline;justify-content:space-between;gap:12px;padding:17px 20px;border:1.5px solid var(--line-2);border-radius:8px;transition:background .15s,color .15s,border-color .15s}
.theme__opt:hover{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.theme__opt span{font-family:var(--display);font-weight:800;font-size:21px;line-height:1;text-transform:uppercase;letter-spacing:.02em}
.theme__opt b{font-size:15px;font-weight:600}
.themepage__ship{margin:18px 0 0;font-size:13.5px;color:var(--ink-2)}
@media (max-width:860px){ .themepage__grid{grid-template-columns:1fr} }

/* The gear heading is the route to this comic's theme page. */
#gear-link:hover{text-decoration:underline;text-underline-offset:5px;text-decoration-thickness:2px}

/* Tight: pills carry their own padding, so the wide gap inherited from the
   text-link version left them reading as three separate controls. */
.filters__kinds{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.filters__kinds[hidden]{display:none}

/* Views sit on the title line: three rows of chrome before the first product
   was two too many. The note keeps the right edge. */
/* Title-to-toggle stays about double the gap inside the toggle, so the pair
   keeps reading as one control however tight the row gets. */
.shoppage__head{align-items:baseline;gap:clamp(14px,1.9vw,26px)}
.shoppage__head .views{margin-top:0}
.shoppage__head .shoppage__note{margin-left:auto}
@media (max-width:720px){
  .shoppage__head .shoppage__note{margin-left:0;width:100%}
}

/* Sort menu. Built rather than a native select — an <option> list is drawn by
   the OS and arrives as a white system menu whatever the page asks for. Same
   popover shape as the calendar, so the site has one menu pattern. */
.sortmenu{position:relative;margin-left:auto}
.sortmenu__btn{
  display:flex;align-items:center;gap:7px;cursor:pointer;
  padding:6px 2px 7px;border-bottom:2px solid var(--line-2);
  font-weight:700;font-size:12.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-2);
}
.sortmenu__btn .ic{font-size:15px;transition:transform .15s}
.sortmenu__btn:hover,.sortmenu__btn[aria-expanded="true"]{color:var(--ink);border-bottom-color:var(--ink)}
.sortmenu__btn[aria-expanded="true"] .ic{transform:rotate(180deg)}
.sortmenu__list{
  position:absolute;z-index:30;top:calc(100% + 8px);right:0;min-width:210px;
  margin:0;padding:6px;list-style:none;
  background:var(--paper);border:1px solid var(--line-2);border-radius:11px;
  box-shadow:0 14px 34px rgba(30,30,30,.17);
}
.sortmenu__list[hidden]{display:none}
.sortmenu__list button{
  width:100%;text-align:left;cursor:pointer;
  padding:9px 11px;border-radius:7px;
  font-weight:600;font-size:14px;color:var(--ink-2);
}
.sortmenu__list button:hover{background:var(--paper-3);color:var(--ink)}
.sortmenu__list button[aria-selected="true"]{background:var(--ink);color:var(--paper)}
.filters__count{margin-left:clamp(14px,2vw,26px)}

/* ═══════════════════════════════════════════════════════════
   Product page — one theme, one product, one price
   Fixed price, so no "from" anywhere here: the visitor is looking at exactly
   one thing that costs exactly one amount.
   ═══════════════════════════════════════════════════════════ */
/* Same gap from the masthead rule to the page's first line as everywhere
   else — this and .checkout were the only two on a different scale. */
.productpage{display:block;padding-top:clamp(20px,2.4vw,32px);padding-bottom:clamp(56px,6vw,96px)}
.productpage__kind{
  margin:0 0 12px;font-size:13px;font-weight:600;
  letter-spacing:.09em;text-transform:uppercase;color:var(--red);
}
.productpage__price{
  margin:14px 0 30px;font-family:var(--display);font-weight:800;
  font-size:clamp(30px,3vw,40px);line-height:1;
}
.sizes{margin:0 0 28px}
.sizes__label{
  margin:0 0 12px;font-size:12.5px;font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--ink-2);
}
.sizes__row{display:flex;flex-wrap:wrap;gap:9px}
.sizes__btn{
  cursor:pointer;min-width:52px;padding:13px 15px;border-radius:8px;
  border:1.5px solid var(--line-2);
  font-weight:700;font-size:13px;color:var(--ink-2);
  transition:background .15s,color .15s,border-color .15s;
}
.sizes__btn:hover{color:var(--ink);border-color:var(--ink)}
.sizes__btn.is-on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.productpage__add{width:100%;justify-content:center;padding:18px 22px;font-size:14px}
.productpage__detail{margin:26px 0 0;font-size:15px;line-height:1.6;color:var(--ink-2)}
.productpage__also{
  margin:26px 0 0;padding-top:20px;border-top:1px solid var(--line);
  font-size:13.5px;color:var(--ink-2);
}
.productpage__also a{font-weight:600;color:var(--ink)}
.productpage__also a:hover{text-decoration:underline;text-underline-offset:4px}
.productpage__also a + a{margin-left:14px}

/* Rail of alternate views, down the left of the stage. Thumbs are navigation
   rather than product views, so `cover` is right here even though the stage
   itself never crops. Every shot is 5:7, so swapping one never moves the page. */
.gallery{display:grid;grid-template-columns:auto minmax(0,1fr);gap:clamp(20px,2.4vw,36px);align-items:start}
.gallery__rail{display:grid;gap:11px;align-content:start}
.gallery__thumb{
  display:block;cursor:pointer;overflow:hidden;
  width:clamp(58px,5.2vw,80px);aspect-ratio:5/7;
  border:1.5px solid var(--line);background:var(--paper-3);
  opacity:.6;transition:opacity .15s,border-color .15s;
}
.gallery__thumb img{width:100%;height:100%;object-fit:cover;display:block}
.gallery__thumb:hover{opacity:1}
.gallery__thumb.is-on{opacity:1;border-color:var(--ink)}

/* On a phone a vertical rail eats the width the artwork needs, so it lies down
   underneath instead. */
@media (max-width:560px){
  .gallery{grid-template-columns:1fr}
  .gallery__rail{order:2;grid-auto-flow:column;grid-auto-columns:60px;justify-content:start}
  .themepage__art{order:1}
}

/* ═══════════════════════════════════════════════════════════
   Cart drawer
   Slides over the page instead of replacing it. With ~200 designs the whole
   point is to keep browsing, and losing your place to confirm one $4 sticker
   is a bad trade. Checkout gets a real page — see checkout.html.
   ═══════════════════════════════════════════════════════════ */
.drawer{position:fixed;inset:0;z-index:80}
.drawer[hidden]{display:none}
.drawer__veil{position:absolute;inset:0;background:rgba(21,20,18,.45)}
.drawer__panel:focus{outline:none}
.drawer__panel{
  --drawer-pad:clamp(18px,3vw,26px);
  position:absolute;top:0;right:0;bottom:0;width:min(430px,92vw);
  display:flex;flex-direction:column;
  background:var(--paper);border-left:2px solid var(--ink);
  box-shadow:-18px 0 44px rgba(30,30,30,.22);
  animation:drawer-in .22s cubic-bezier(.2,.7,.3,1);
}
@keyframes drawer-in{from{transform:translateX(100%)}}
@media (prefers-reduced-motion:reduce){.drawer__panel:focus{outline:none}
.drawer__panel{animation:none}}

/* The rules are inset to the panel's padding rather than being borders on the
   head and foot, which ran the full panel width and overhung the content they
   were separating. Same pseudo-element trick as the masthead rule. */
.drawer__head{
  position:relative;
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:22px var(--drawer-pad) 18px;
}
.drawer__head::after{
  content:"";position:absolute;bottom:0;
  left:var(--drawer-pad);right:var(--drawer-pad);
  height:2px;background:var(--ink);
}
.drawer__title{
  margin:0;font-family:var(--display);font-weight:900;font-size:26px;
  line-height:1;text-transform:uppercase;
}
.drawer__close{
  cursor:pointer;display:grid;place-items:center;flex:none;
  width:34px;height:34px;border-radius:999px;font-size:22px;line-height:1;
  color:var(--ink-2);
}
.drawer__close:hover{background:var(--paper-3);color:var(--ink)}

.drawer__body{flex:1;overflow-y:auto;padding:6px var(--drawer-pad)}
.drawer__empty{margin:40px 0;text-align:center;color:var(--ink-2);font-size:15px}
.drawer__empty a{font-weight:700;color:var(--ink);text-decoration:underline;text-underline-offset:4px}

.line{display:grid;grid-template-columns:62px minmax(0,1fr) auto;gap:14px;
      padding:18px 0;border-bottom:1px solid var(--line)}
.line:last-child{border-bottom:0}
.line__thumb{width:62px;aspect-ratio:5/7;object-fit:cover;display:block;
             border:1px solid var(--line);background:var(--paper-3)}
.line__name{margin:0;font-family:var(--display);font-weight:800;font-size:17px;
            line-height:1.1;text-transform:uppercase}
.line__meta{margin:4px 0 10px;font-size:12.5px;color:var(--ink-2)}
.line__price{margin:0;font-weight:700;font-size:15px;white-space:nowrap}

.qty{display:flex;align-items:center;gap:2px}
.qty button{
  cursor:pointer;width:28px;height:28px;border:1.5px solid var(--line-2);
  font-size:15px;font-weight:700;line-height:1;color:var(--ink-2);
}
.qty button:first-child{border-radius:7px 0 0 7px}
.qty button:last-of-type{border-radius:0 7px 7px 0;border-left-width:0}
.qty button:hover{color:var(--ink);border-color:var(--ink)}
.qty span{min-width:34px;text-align:center;font-weight:700;font-size:14px;
          border-block:1.5px solid var(--line-2);line-height:25px;height:28px}
/* Remove sits beside the stepper, not inside it: as a child of .qty it picked
   up that group's 28px button box and its text spilled out of the border. */
.line__actions{display:flex;align-items:center;gap:14px}
.line__rm{cursor:pointer;font-size:12.5px;color:var(--ink-2);
          text-decoration:underline;text-underline-offset:3px}
.line__rm:hover{color:var(--red)}

.drawer__foot{position:relative;padding:20px var(--drawer-pad) 24px}
.drawer__foot::before{
  content:"";position:absolute;top:0;
  left:var(--drawer-pad);right:var(--drawer-pad);
  height:2px;background:var(--ink);
}
.drawer__sub{display:flex;justify-content:space-between;align-items:baseline;
             margin:0 0 4px;font-size:15px}
.drawer__sub b{font-family:var(--display);font-weight:800;font-size:26px;line-height:1}
.drawer__ship{margin:0 0 16px;font-size:12.5px;color:var(--ink-2)}
.drawer__go{width:100%;justify-content:center;padding:17px 22px;font-size:14px}

/* ── Checkout ────────────────────────────────────────────────────────────── */
.checkout{padding-top:clamp(20px,2.4vw,32px);padding-bottom:clamp(56px,6vw,96px)}
.checkout__grid{display:grid;grid-template-columns:minmax(0,1fr) clamp(300px,32vw,400px);
                gap:clamp(30px,4vw,66px);align-items:start}
@media (max-width:840px){.checkout__grid{grid-template-columns:1fr}}
.checkout__title{margin:0 0 26px;font-family:var(--display);font-weight:900;
                 font-size:clamp(38px,5vw,64px);line-height:.95;text-transform:uppercase}
.fieldset{margin:0 0 30px;border:0;padding:0}
.fieldset__legend{
  margin:0 0 14px;padding:0;font-family:var(--display);font-weight:800;
  font-size:20px;line-height:1;text-transform:uppercase;
}
.field{margin:0 0 14px}
.field label{display:block;margin:0 0 6px;font-size:12.5px;font-weight:700;
             letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2)}
.field input{
  width:100%;font:inherit;font-size:15px;color:var(--ink);
  padding:13px 14px;border-radius:8px;
  border:1.5px solid var(--line-2);background:var(--paper);
}
.field input:focus{outline:none;border-color:var(--ink)}
.field--split{display:grid;grid-template-columns:1fr 1fr;gap:14px}

.summary{padding:24px;border:2px solid var(--ink);background:var(--paper-2)}
.summary__title{margin:0 0 18px;font-family:var(--display);font-weight:800;
                font-size:20px;line-height:1;text-transform:uppercase}
.summary__row{display:flex;justify-content:space-between;gap:14px;margin:0 0 9px;
              font-size:14px;color:var(--ink-2)}
.summary__row b{color:var(--ink);font-weight:700;white-space:nowrap}
/* Separates the running totals from the line items above them. */
.summary__row--gap{margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}
.summary__total{display:flex;justify-content:space-between;align-items:baseline;
                margin:16px 0 0;padding-top:16px;border-top:2px solid var(--ink);font-size:15px}
.summary__total b{font-family:var(--display);font-weight:900;font-size:30px;line-height:1}
.summary__go{width:100%;justify-content:center;margin-top:20px;padding:17px 22px;font-size:14px}
.summary__note{margin:14px 0 0;font-size:12.5px;line-height:1.5;color:var(--ink-2)}

/* ═══════════════════════════════════════════════════════════
   More comics
   The archive is the product for a daily strip, and the calendar is a
   deliberate act you have to decide to take. This is passive: you meet it on
   the way past. It also fills the slot under the join banner, which breathes
   between roughly 60px and 240px depending on window height — the comic is
   sized in svh, so a short window shortens it and drops everything upward.
   A single scrolling row survives that; a boxed module would not.
   ═══════════════════════════════════════════════════════════ */
.prev{grid-area:prev}
/* Label plus handwritten aside, same pairing as the share block: the label
   names the thing, the note says what to do with it. */
.prev__head{margin:0 0 12px;display:flex;align-items:baseline;gap:clamp(12px,1.6vw,22px);flex-wrap:wrap}
.prev__note{font-family:var(--hand);font-weight:600;font-size:19px;color:var(--red)}
@media (max-width:560px){ .prev__note{display:none} }
/* One row that scrolls, not a wrapping block: a month wrapped to three rows
   today and five by the 31st, so the page changed height through the month.
   Arrows flank the row rather than floating over it, matching the comic viewer
   where the controls were moved off the artwork. */
.prev__deck{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:12px;align-items:center}
.prev__arrow{
  width:36px;height:36px;border-radius:50%;flex:none;
  display:grid;place-items:center;cursor:pointer;
  background:transparent;color:var(--ink);
  border:1.5px solid var(--line-2);
  transition:background .15s,color .15s,border-color .15s,opacity .15s;
}
.prev__arrow:hover:not(:disabled){background:var(--ink);color:var(--paper);border-color:var(--ink)}
.prev__arrow:disabled{opacity:.26;cursor:default}
.prev__arrow .ic{font-size:17px;stroke-width:2.1}
.prev__row{
  display:flex;flex-wrap:nowrap;
  gap:clamp(9px,1vw,14px);
  overflow-x:auto;scrollbar-width:none;
  /* No scroll-behavior here on purpose: the arrows ask for smooth scrolling
     explicitly via scrollBy, and leaving it off keeps the initial jump to the
     right edge instant without having to fight it. */
}
.prev__row::-webkit-scrollbar{display:none}
.prev__row::-webkit-scrollbar{display:none}
.prev[hidden]{display:none}
/* Wide enough for the longest caption, “Wednesday 12”, on one line. Wrapping
   it would leave the tiles misaligned wherever a day name is short. */
.prev__item{flex:none;cursor:pointer;display:block;width:clamp(96px,8.4vw,112px)}
.prev__tile{
  display:block;overflow:hidden;aspect-ratio:5/7;
  border:1.5px solid var(--line);background:var(--paper-3);
  opacity:.72;transition:opacity .15s,border-color .15s;
}
.prev__tile img{width:100%;height:100%;object-fit:cover;display:block}
.prev__item:hover .prev__tile{opacity:1;border-color:var(--ink)}
.prev__day{
  display:block;margin-top:7px;font-size:11px;font-weight:700;
  letter-spacing:.02em;text-transform:uppercase;white-space:nowrap;
  color:var(--ink-2);
}
.prev__item:hover .prev__day{color:var(--ink)}

/* Closes the lede, after the handwritten line so that note stays attached to
   the origin story it is confirming. */
.about__plug{margin-top:18px}

/* The plug appears twice on purpose. The second one names itself as a repeat,
   which is the only way saying the same thing twice reads as a joke rather
   than as an oversight. */
.about__plug2{margin:10px 0 2px}

/* One more thing. A postscript, not a feature: it changes when there is
   something to say and sits unchanged when there isn't, so it can never be
   stale the way a dated panel would be. */
.more{grid-area:more;padding-top:clamp(18px,2vw,26px);border-top:1px solid var(--line)}
.more__head{margin:0 0 8px}
.more__body{margin:0;font-size:16.5px;line-height:1.55;color:var(--ink-2);max-width:62ch}

/* Shown instead of thumbnails when a month has nothing before today. */
.prev__none{margin:0;padding:6px 0;font-size:15px;color:var(--ink-2)}

.cal-btn__label{
  font-size:11.5px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;white-space:nowrap;
}

/* Today's other comics, in the rail under the dateline. Only appears when a day
   has more than one — below the stage it sat under the fold, so a reader could
   take one comic and leave never knowing there were three. */
.today{margin:0 0 16px}
.today[hidden]{display:none}
.today .prev__row{gap:7px;overflow:visible}
.today .prev__item{width:clamp(50px,4.4vw,58px)}
.today .prev__item.is-on .prev__tile{opacity:1;border-color:var(--ink);border-width:2.5px}
.today .prev__day{margin-top:5px;font-size:10px;color:var(--red)}

/* Confirms a copy actually happened. Without it the Instagram and copy-link
   buttons look broken — they fire, but nothing on screen changes. */
.share__toast{
  margin:10px 0 0;font-size:13px;font-weight:600;color:var(--red);
}
.share__toast[hidden]{display:none}
