/* ============================================================
   Glass Fusing Tools — site stylesheet
   One file, no build step, no dependencies.

   COLOR RULES (verified against WCAG, do not improvise):
     marigold / pink / teal fills   -> INK text only, never white
     aubergine fill                 -> WHITE text only, never ink
     For colored TEXT on the paper ground use the *-ink variants.
     The bright fills sit below 3:1 against the paper ground on purpose;
     the 2px ink border is what carries the boundary contrast, so every
     filled element must keep its border.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter:wght@400;500;600;700&family=DM+Mono:wght@400;500&display=swap');

:root{
  /* --- ground: cool near-white, from the Hart Glass palette ---- */
  --paper:      #F7F6FC;
  --paper-2:    #EDEBF7;
  --white:      #FFFFFF;
  --ink:        #16111C;   /* near-black with a violet cast, not pure black */
  --ink-2:      #4F4757;   /* muted body text — 8.2:1 on paper */
  --line:       #DAD6EA;

  /* --- the three brights: use as FILLS, always with INK text ---- */
  --marigold:   #F5AC23;   /* ink 9.6:1 */
  --pink:       #EE5D8A;   /* ink 5.8:1 */
  --teal:       #22BFB2;   /* ink 8.1:1 */

  /* --- the anchor: use as a FILL, always with WHITE text -------- */
  --aubergine:  #2C1A38;   /* white 16:1 */

  /* --- ink variants: use as TEXT on the paper ground ------------ */
  --marigold-ink: #7A4F00;
  --pink-ink:     #B51F54;
  --teal-ink:     #0A736B;
  /* aubergine already reads as text on paper at 14.9:1 */

  /* --- section accent (overridden per page) ------------------- */
  --accent:      var(--marigold);
  --accent-ink:  var(--marigold-ink);
  --accent-on:   var(--on-bright);   /* text that sits on --accent */

  /* --- semantic roles -------------------------------------------
     The names above are the PALETTE. Components use the roles below,
     so a brand colour never silently carries a meaning.            */
  --surface:      var(--white);
  --surface-2:    var(--paper-2);
  --on-surface:   var(--ink);
  --on-surface-2: var(--ink-2);

  /* Text and edges sitting ON a bright fill. The brights stay bright
     in dark mode, so this never inverts. */
  --on-bright:  #16111C;
  /* The structural 2px edge and hard shadow. This DOES invert, so a
     card keeps an edge against a dark ground. */
  --outline:    #16111C;

  /* --- state roles ----------------------------------------------
     Deliberately NOT the brand brights: pink means "pink", not
     "warning". Warnings must survive a rebrand.                    */
  --warn:       #F2A20C;  --warn-ink:   #7A4A00;  --warn-bg:   #FDF3DD;
  --danger:     #E23D4E;  --danger-ink: #A81228;  --danger-bg: #FCE9EB;
  --ok:         #1FA971;  --ok-ink:     #0A6B45;  --ok-bg:     #E6F6EF;

  /* Preview and print surfaces stand for paper and glass. They are
     physical things, so they stay light even in dark mode. */
  --sheet:      #FFFFFF;
  --sheet-line: #16111C;

  /* --- space: 4/8 rhythm -------------------------------------- */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
  --s-5: 24px; --s-6: 32px; --s-7: 48px; --s-8: 64px; --s-9: 96px;

  --radius:    18px;
  --radius-sm: 10px;
  --radius-pill: 999px;

  --border: 2px solid var(--outline);
  --shadow:       4px 4px 0 var(--outline);
  --shadow-lift:  7px 7px 0 var(--outline);
  --shadow-sm:    3px 3px 0 var(--outline);

  --wrap: 1180px;
  --measure: 68ch;

  --ease: cubic-bezier(.2,.7,.3,1);
  --t: 200ms;
}

/* ---------- dark mode -----------------------------------------
   Designed with the light palette, not inverted from it.

   The rule that makes this work: the three brights and the aubergine
   are GLASS. A sheet of Marigold does not change colour because the
   room got dark, so filled elements keep their fill, their dark text
   and their dark edge in both modes (--on-bright). What inverts is the
   room: the ground, the cards, the body text and the structural edge
   (--outline), so a card still reads as a card against a dark page.

   Preview and print surfaces also stay light — they stand for paper
   and for glass on a light table, and they have to print.           */
@media (prefers-color-scheme: dark){
  :root{
    --paper:   #17131F;
    --paper-2: #221B2C;
    --white:   #1E1826;        /* card / input surface, not literal white */
    --ink:     #F3F0F8;        /* 15.8:1 on --paper */
    --ink-2:   #BDB4CC;        /*  8.6:1 on --paper */
    --line:    #3A3145;
    --outline: #CFC6DE;        /* the 2px edge, now light */

    /* coloured TEXT has to lighten or it disappears on the dark ground */
    --marigold-ink: #F7C35C;
    --pink-ink:     #F79BB6;
    --teal-ink:     #5FD8CD;

    /* state text and grounds, re-picked for a dark surface */
    --warn-ink:   #F4C265;  --warn-bg:   #33270E;
    --danger-ink: #F79AA5;  --danger-bg: #3A1218;
    --ok-ink:     #6FDCA9;  --ok-bg:     #0E2E20;
  }
  /* the footer is an ink slab in light mode; on a dark page it needs
     to separate from the ground by an edge instead of by weight */
  .site-footer{ background: var(--paper-2); color: var(--ink); border-top: 2px solid var(--outline); }
  /* .btn-ink inverts to stay a contrast button, not a disappearing one */
  .btn-ink{ background: var(--ink); color: var(--paper); }
}

*,*::before,*::after{ box-sizing: border-box; }

html{ -webkit-text-size-adjust: 100%; }

body{
  margin:0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Per-section accent. Set data-section on <body>.
   Three brights carry ink text; the aubergine anchor carries white. */
body[data-section="tools"]    { --accent: var(--marigold);  --accent-ink: var(--marigold-ink); --accent-on: var(--on-bright); }
body[data-section="patterns"] { --accent: var(--pink);      --accent-ink: var(--pink-ink);     --accent-on: var(--on-bright); }
body[data-section="guides"]   { --accent: var(--teal);      --accent-ink: var(--teal-ink);     --accent-on: var(--on-bright); }
body[data-section="projects"] { --accent: var(--aubergine); --accent-ink: var(--aubergine);    --accent-on: var(--white); }
body[data-section="about"]    { --accent: var(--aubergine); --accent-ink: var(--aubergine);    --accent-on: var(--white); }
body[data-section="legal"]    { --accent: var(--aubergine); --accent-ink: var(--aubergine);    --accent-on: var(--white); }

/* ---------- typography ---------------------------------------- */
h1,h2,h3,h4{
  font-family: "Instrument Serif", Georgia, "Times New Roman", serif;
  font-weight: 400;          /* Instrument Serif ships one weight only */
  line-height: 1.08;         /* a narrow serif can sit tighter than a wide one */
  letter-spacing: 0;
  margin: 0;
  text-wrap: balance;
}
/* Sizes are NOT a free choice — they follow the face. Measured at the same
   px, the previous display face set "Glass Fusing Cutting Calculator" at
   1406px where Instrument Serif sets it at 1054px, so every heading step is
   multiplied by 1.357 to hold the same optical size. (The face before that
   was condensed and needed 0.805, the other way.) */
h1{ font-size: clamp(2.92rem, 7.9vw, 5.1rem); }
h2{ font-size: clamp(2.3rem, 5vw, 3.45rem); }
h3{ font-size: clamp(1.5rem, 2.85vw, 1.9rem); }
h4{ font-size: 1.38rem; font-weight: 400; letter-spacing: 0; }

p{ margin: 0 0 var(--s-4); }
p:last-child{ margin-bottom: 0; }

.lede{ font-size: clamp(1.1rem, 2vw, 1.3rem); color: var(--ink-2); line-height: 1.55; }
.measure{ max-width: var(--measure); }

a{ color: var(--accent-ink); text-underline-offset: 3px; text-decoration-thickness: 2px; }
a:hover{ text-decoration-thickness: 3px; }

code,.mono,.style-no{
  font-family: "DM Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-feature-settings: "tnum" 1;
  font-size: 0.9em;
}

/* Eyebrow / section label with the swatch-chip motif */
.eyebrow{
  display:inline-flex; align-items:center; gap: var(--s-2);
  font-size: .8rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-2); margin: 0 0 var(--s-3);
}
.eyebrow::before{
  content:""; width: 14px; height: 14px; border-radius: 4px;
  background: var(--accent); border: 2px solid var(--on-bright); flex: none;
}

/* ---------- layout -------------------------------------------- */
.wrap{ width:100%; max-width: var(--wrap); margin-inline:auto; padding-inline: var(--s-5); }
section{ padding-block: var(--s-8); }
section.tight{ padding-block: var(--s-7); }
@media (min-width: 768px){ section{ padding-block: var(--s-9); } }

.band{ background: var(--paper-2); border-block: var(--border); }

.grid{ display:grid; gap: var(--s-5); }
@media (min-width: 700px){ .grid-2{ grid-template-columns: repeat(2,1fr); } }
@media (min-width: 700px){ .grid-3{ grid-template-columns: repeat(2,1fr); } }
@media (min-width: 1000px){ .grid-3{ grid-template-columns: repeat(3,1fr); } }

.stack > * + *{ margin-top: var(--s-4); }
.stack-lg > * + *{ margin-top: var(--s-6); }

/* ---------- skip link ------------------------------------------ */
.skip{
  position:absolute; left: var(--s-4); top: -100px; z-index: 200;
  background: var(--marigold); color: var(--on-bright); border: 2px solid var(--on-bright);
  padding: var(--s-3) var(--s-4); border-radius: var(--radius-sm); font-weight:700;
  box-shadow: var(--shadow-sm); transition: top var(--t) var(--ease);
}
.skip:focus{ top: var(--s-4); }

/* ---------- focus ---------------------------------------------- */
:focus-visible{
  outline: 3px solid var(--marigold-ink);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------- header --------------------------------------------- */
.site-header{
  position: sticky; top:0; z-index: 100;
  background: var(--paper);
  border-bottom: var(--border);
}
.header-inner{ display:flex; align-items:center; justify-content:space-between; gap: var(--s-4); min-height: 68px; }

.logo{
  display:inline-flex; align-items:center; gap: var(--s-3);
  font-family:"Instrument Serif",Georgia,serif; font-weight:400; font-size:1.74rem;
  letter-spacing:-.02em; color: var(--ink); text-decoration:none; flex: none;
  min-height: 44px;
}
.logo:hover{ text-decoration: none; }
.logo-mark{ display:block; width: 34px; height:34px; flex:none; }

.site-nav{ display:none; }
@media (min-width: 900px){
  .site-nav{ display:flex; align-items:center; gap: var(--s-1); }
}
.site-nav a{
  display:inline-block; padding: var(--s-2) var(--s-3);
  color: var(--ink); text-decoration:none; font-weight:600; font-size: .97rem;
  border-radius: var(--radius-sm); border: 2px solid transparent;
  transition: background var(--t) var(--ease), border-color var(--t) var(--ease);
}
.site-nav a:hover{ background: var(--paper-2); border-color: var(--line); }
.site-nav a[aria-current="page"]{
  background: var(--accent); color: var(--accent-on); border-color: var(--on-bright);
  box-shadow: var(--shadow-sm);
}

.nav-toggle{
  display:inline-flex; align-items:center; justify-content:center; gap: var(--s-2);
  min-height: 44px; padding: var(--s-2) var(--s-4);
  background: var(--paper-2); color: var(--ink);
  border: var(--border); border-radius: var(--radius-sm);
  font: inherit; font-weight:700; font-size:.9rem; cursor:pointer;
  box-shadow: var(--shadow-sm);
}
@media (min-width: 900px){ .nav-toggle{ display:none; } }

.mobile-nav{ display:none; border-top: 2px solid var(--line); padding-block: var(--s-3) var(--s-5); }
.mobile-nav[data-open="true"]{ display:block; }
@media (min-width: 900px){ .mobile-nav{ display:none !important; } }
.mobile-nav a{
  display:block; padding: var(--s-3) var(--s-4); min-height:44px;
  color: var(--ink); text-decoration:none; font-weight:600;
  border-radius: var(--radius-sm);
}
.mobile-nav a + a{ margin-top: var(--s-1); }
.mobile-nav a:hover{ background: var(--paper-2); }
.mobile-nav a[aria-current="page"]{ background: var(--accent); color: var(--accent-on); border:2px solid var(--on-bright); }

/* ---------- buttons -------------------------------------------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap: var(--s-2);
  min-height: 48px; padding: var(--s-3) var(--s-5);
  font: inherit; font-weight: 700; font-size: 1rem; line-height:1.2;
  text-decoration:none; cursor:pointer;
  border: var(--border); border-radius: var(--radius-pill);
  box-shadow: var(--shadow);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease), background var(--t) var(--ease);
}
.btn:hover{ transform: translate(-2px,-2px); box-shadow: var(--shadow-lift); text-decoration:none; }
.btn:active{ transform: translate(2px,2px); box-shadow: 1px 1px 0 var(--outline); }
.btn-primary{ background: var(--accent); color: var(--accent-on); border-color: var(--on-bright); }
.btn-ink{ background: var(--ink); color: var(--paper); }
.btn-quiet{ background: var(--paper); color: var(--ink); }
.btn-sm{ min-height: 44px; padding: var(--s-2) var(--s-4); font-size: .93rem; }

.btn[disabled],.btn[aria-disabled="true"]{
  opacity:.45; cursor: not-allowed; transform:none; box-shadow: var(--shadow);
}

/* ---------- cards ---------------------------------------------- */
.card{
  display:block; position:relative;
  background: var(--white);
  border: var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--s-5);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
a.card{ text-decoration:none; color: var(--ink); }
a.card:hover{ transform: translate(-3px,-3px); box-shadow: var(--shadow-lift); }
a.card:hover .card-title{ text-decoration: underline; text-decoration-thickness:3px; text-underline-offset:3px; }

.card-title{ margin-bottom: var(--s-2); font-size: clamp(1.83rem, 3.5vw, 2.38rem); }
.card p{ color: var(--ink-2); font-size: .97rem; }

/* color-block card: fill the whole card with an accent */
/* `a.card` (0-1-1) out-specifies a bare `.card-fill` (0-1-0), so without the
   `a.card.card-fill` selector a dark fill like aubergine renders INK text on
   it — unreadable. Keep both selectors. No opacity here either: it eats
   contrast on exactly the cards that have least to spare. */
.card-fill, a.card.card-fill{ background: var(--card-bg, var(--accent)); color: var(--card-fg, var(--on-bright)); border-color: var(--on-bright); }
.card-fill p, a.card.card-fill p{ color: inherit; }

/* card tags */
.tag{
  display:inline-flex; align-items:center; gap: var(--s-2);
  padding: var(--s-1) var(--s-3); min-height: 26px;
  font-size:.75rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  border: 2px solid var(--ink); border-radius: var(--radius-pill);
  background: var(--paper-2); color: var(--ink);
}
.tag-soon{ background: var(--marigold); color: var(--on-bright); border-color: var(--on-bright); }
.tag-live{ background: var(--teal); color: var(--on-bright); border-color: var(--on-bright); }

/* ---------- hero ------------------------------------------------ */
.hero{ padding-block: var(--s-8) var(--s-8); border-bottom: var(--border); position:relative; overflow:hidden; }
@media (min-width:768px){ .hero{ padding-block: var(--s-9); } }
.hero-inner{ display:grid; gap: var(--s-7); align-items:center; }
@media (min-width: 900px){ .hero-inner{ grid-template-columns: 1.05fr .95fr; gap: var(--s-8); } }
.hero h1{ margin-bottom: var(--s-5); }
.hero-actions{ display:flex; flex-wrap:wrap; gap: var(--s-3); margin-top: var(--s-6); }
.hero-art{ width:100%; height:auto; display:block; }

/* ---------- swatch strip (signature motif) ---------------------- */
.swatch-strip{ display:flex; gap: var(--s-2); flex-wrap:wrap; }
.swatch{
  width: 30px; height: 30px; border-radius: 8px;
  border: 2px solid var(--ink); flex:none;
}

/* ---------- section head ---------------------------------------- */
.section-head{ margin-bottom: var(--s-6); }
.section-head h2{ margin-bottom: var(--s-3); }
.section-head .lede{ max-width: var(--measure); }
.head-row{ display:flex; flex-wrap:wrap; align-items:flex-end; justify-content:space-between; gap: var(--s-4); }

/* ---------- numbered steps -------------------------------------- */
.steps{ list-style:none; margin:0; padding:0; display:grid; gap: var(--s-5); counter-reset: step; }
@media (min-width:700px){ .steps{ grid-template-columns: repeat(3,1fr); } }
.steps li{
  counter-increment: step;
  background: var(--white); border: var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: var(--s-5);
}
.steps li::before{
  content: counter(step);
  display:flex; align-items:center; justify-content:center;
  width: 42px; height:42px; margin-bottom: var(--s-4);
  font-family:"Instrument Serif",Georgia,serif; font-weight:400; font-size:1.79rem;
  background: var(--accent); color: var(--accent-on);
  border: var(--border); border-radius: var(--radius-sm);
}
.steps h3{ font-size:1.56rem; margin-bottom: var(--s-2); }
.steps p{ color: var(--ink-2); font-size:.97rem; }

/* ---------- empty state ------------------------------------------ */
.empty{
  border: 2px dashed var(--ink); border-radius: var(--radius);
  background: var(--paper-2);
  padding: var(--s-7) var(--s-5);
  text-align:center;
}
.empty h2,.empty h3{ margin-bottom: var(--s-3); font-size: clamp(1.83rem, 3.5vw, 2.38rem); }
.empty p{ color: var(--ink-2); max-width: 52ch; margin-inline:auto; }
.empty .btn{ margin-top: var(--s-5); }

/* ---------- prose (guides) ---------------------------------------- */
.prose{ max-width: var(--measure); }
.prose h2{ margin-top: var(--s-8); margin-bottom: var(--s-4); }
.prose h3{ margin-top: var(--s-6); margin-bottom: var(--s-3); }
.prose > :first-child{ margin-top: 0; }
.prose ul,.prose ol{ margin: 0 0 var(--s-4); padding-left: var(--s-5); }
.prose li{ margin-bottom: var(--s-2); }
.prose li::marker{ color: var(--accent-ink); font-weight:700; }
.prose strong{ font-weight:700; }

.callout{
  border: var(--border); border-left-width: 8px; border-radius: var(--radius-sm);
  background: var(--paper-2); padding: var(--s-5); margin-block: var(--s-6);
}
.callout .eyebrow{ margin-bottom: var(--s-2); }
/* A brand colour must not be the only carrier of meaning, and every
   callout already names itself in its .eyebrow, so colour is backup. */
.callout-warn{ border-left-color: var(--warn); background: var(--warn-bg); }
.callout-warn .eyebrow{ color: var(--warn-ink); }
.callout-warn .eyebrow::before{ background: var(--warn); }
.callout-note{ border-left-color: var(--teal); }

/* ---------- tables ------------------------------------------------- */
.table-scroll{ overflow-x:auto; margin-block: var(--s-5); border: var(--border); border-radius: var(--radius); background: var(--white); }
table{ border-collapse: collapse; width:100%; min-width: 520px; font-size:.95rem; }
th,td{ text-align:left; padding: var(--s-3) var(--s-4); border-bottom: 2px solid var(--line); vertical-align: top; }
thead th{ background: var(--paper-2); font-weight:700; border-bottom: var(--border); }
tbody tr:last-child td{ border-bottom: none; }
td.num,th.num{ font-family:"DM Mono",monospace; font-feature-settings:"tnum" 1; white-space:nowrap; }

/* ---------- footer --------------------------------------------------- */
.site-footer{ border-top: var(--border); background: var(--ink); color: var(--paper); padding-block: var(--s-7); margin-top: var(--s-8); }
.site-footer a{ color: var(--paper); text-decoration: none; }
.site-footer a:hover{ text-decoration: underline; text-decoration-thickness:2px; }
.footer-grid{ display:grid; gap: var(--s-6); }
@media (min-width: 700px){ .footer-grid{ grid-template-columns: 1.4fr 1fr 1fr; } }
.footer-grid h2{ font-family:"Instrument Serif",Georgia,serif; font-weight:400; font-size:.9rem; letter-spacing:.1em; text-transform:uppercase; color:#BDB5CE; margin-bottom: var(--s-3); }
.footer-links{ list-style:none; margin:0; padding:0; }
.footer-links li{ margin-bottom: var(--s-2); }
.footer-note{ margin-top: var(--s-6); padding-top: var(--s-5); border-top: 2px solid #3A2F26; color:#BDB5CE; font-size:.88rem; }

/* ---------- utilities -------------------------------------------------- */
.visually-hidden{
  position:absolute!important; width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}
.center{ text-align:center; }
.mt-6{ margin-top: var(--s-6); }
.mt-7{ margin-top: var(--s-7); }

/* ---------- motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important; animation-iteration-count:1!important;
    transition-duration:.001ms!important; scroll-behavior:auto!important;
  }
  .btn:hover,a.card:hover{ transform:none; }
}

/* ---------- section page header ------------------------------------- */
.page-head{
  background: var(--accent); color: var(--accent-on);
  border-bottom: var(--border);
  padding-block: var(--s-7);
}
@media (min-width:768px){ .page-head{ padding-block: var(--s-8); } }
.page-head .eyebrow{ color: inherit; opacity: .85; }
.page-head .eyebrow::before{ background: var(--accent-on); }
.page-head h1{ margin-bottom: var(--s-4); }
.page-head .lede{ color: inherit; opacity: .92; max-width: var(--measure); }

/* breadcrumb */
.crumbs{ font-size:.88rem; margin-bottom: var(--s-4); color: inherit; opacity:.85; }
.crumbs a{ color: inherit; }
.crumbs span{ margin-inline: var(--s-2); }

/* guide meta row */
.meta-row{ display:flex; flex-wrap:wrap; gap: var(--s-3); align-items:center; margin-top: var(--s-5); }

/* ============================================================
   Color Pairing Tool
   ============================================================ */
.tool-layout{ display:grid; gap: var(--s-6); align-items:start; }
@media (min-width: 980px){ .tool-layout{ grid-template-columns: 420px 1fr; gap: var(--s-7); } }

.panel{
  background: var(--white); border: var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: var(--s-5);
}
.panel + .panel{ margin-top: var(--s-5); }
.panel h2{ font-size: 1.7rem; margin-bottom: var(--s-4); }
.panel h3{ font-size: 1.43rem; }

/* --- wheel --- */
.wheel-wrap{ position:relative; width:100%; max-width: 340px; margin-inline:auto; aspect-ratio:1; }
#wheel{
  width:100%; height:100%; display:block; border-radius:50%;
  border: var(--border); box-shadow: var(--shadow); cursor: crosshair;
  touch-action: none;
}
#wheel:focus-visible{ outline: 3px solid var(--marigold-ink); outline-offset: 5px; }
.wheel-marker{
  position:absolute; width: 26px; height:26px; margin:-13px 0 0 -13px;
  border-radius:50%; border: 3px solid var(--ink); background: transparent;
  box-shadow: 0 0 0 2px var(--white) inset; pointer-events:none;
}

/* --- picked readout --- */
.picked{ display:flex; align-items:center; gap: var(--s-4); margin-top: var(--s-5); }
.picked-swatch{ width:64px; height:64px; flex:none; border: var(--border); border-radius: var(--radius-sm); box-shadow: var(--shadow-sm); }
.picked-meta .mono{ font-size: 1rem; font-weight:500; }
.picked-meta small{ display:block; color: var(--ink-2); font-size:.85rem; margin-top:2px; }

/* --- sliders (the keyboard/pointer alternative to dragging the wheel) --- */
.slider-row{ margin-top: var(--s-4); }
.slider-row label{ display:flex; justify-content:space-between; align-items:baseline; font-weight:600; font-size:.9rem; margin-bottom: var(--s-2); }
.slider-row label .val{ font-family:"DM Mono",monospace; font-feature-settings:"tnum" 1; color: var(--ink-2); font-weight:400; }
input[type=range]{
  -webkit-appearance:none; appearance:none; width:100%;
  height: 44px;               /* the real touch target, not the visible track */
  background: transparent;    /* visible track is drawn on the pseudo-elements */
  border: 0; margin: 0; padding: 0; cursor: pointer;
}
input[type=range]::-webkit-slider-runnable-track{
  height: 14px; background: var(--paper-2);
  border: 2px solid var(--ink); border-radius: var(--radius-pill);
}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none; width: 28px; height: 28px; border-radius:50%;
  background: var(--white); border: 3px solid var(--ink); box-shadow: var(--shadow-sm);
  margin-top: -8px;   /* center the 34px thumb box on the 18px track box */
  cursor: grab;
}
input[type=range]::-moz-range-track{
  height: 14px; background: var(--paper-2);
  border: 2px solid var(--ink); border-radius: var(--radius-pill);
}
input[type=range]::-moz-range-thumb{
  width: 24px; height: 24px; border-radius:50%;
  background: var(--white); border: 3px solid var(--ink); cursor: grab;
}
input[type=range]:focus-visible{ outline: 3px solid var(--marigold-ink); outline-offset: 3px; }

/* --- chips (filters + schemes) --- */
.chip-set{ display:flex; flex-wrap:wrap; gap: var(--s-2); }
.chip{
  display:inline-flex; align-items:center; gap: var(--s-2);
  min-height: 44px; padding: var(--s-2) var(--s-4);
  font: inherit; font-size:.9rem; font-weight:600; cursor:pointer;
  background: var(--paper); color: var(--ink);
  border: var(--border); border-radius: var(--radius-pill);
  transition: background var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.chip:hover{ background: var(--paper-2); }
.chip[aria-pressed="true"]{ background: var(--accent); color: var(--accent-on); box-shadow: var(--shadow-sm); }

/* --- match cards --- */
/* auto-fill so the columns respond to the PANEL width, not the viewport —
   this grid sits inside a narrow column and viewport breakpoints get it wrong */
.match-grid{
  display:grid; gap: var(--s-4); list-style:none; margin:0; padding:0;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}

.match{
  display:flex; gap: var(--s-4); align-items:flex-start;
  background: var(--white); border: var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: var(--s-4); height:100%;
}
.match-pair{ display:flex; flex:none; border: 2px solid var(--ink); border-radius: var(--radius-sm); overflow:hidden; }
.match-pair span{ display:block; width: 30px; height: 62px; }
.match-body{ min-width:0; display:block; }
.match-role,.match-name,.match-sub{ display:block; }
.match-role{ font-size:.72rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color: var(--ink-2); }
/* break-word, not anywhere: these are product names, not URLs */
.match-name{ font-weight:700; line-height:1.25; margin:2px 0 4px; overflow-wrap:break-word; }
.match-name a{ color: var(--ink); text-decoration-thickness:2px; }
.match-sub{ font-size:.82rem; color: var(--ink-2); }
.match-sub .style-no{ color: var(--ink); }
.match-flag{
  display:inline-block; white-space:nowrap; margin-top: var(--s-2); padding: 1px var(--s-2);
  font-size:.7rem; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
  border:2px solid var(--on-bright); border-radius: var(--radius-pill); background: var(--marigold); color: var(--on-bright);
}
/* AFTER .match-flag, not before: same specificity, so the later rule is the
   one that wins. Put earlier, this silently did nothing and the reaction
   flag came out the same marigold as "iridescent available". */
.flag-react{
  background: var(--pink);
  /* names of two or three glasses do not fit on one line in a card — the
     unwrapped version ran straight off the edge */
  white-space: normal; max-width: 100%;
}

/* --- saved palettes --- */
.saved-list{ list-style:none; margin:0; padding:0; display:grid; gap: var(--s-3); }
.saved-item{ display:flex; align-items:center; gap: var(--s-3); flex-wrap:wrap; }
.saved-strip{ display:flex; border:2px solid var(--ink); border-radius: var(--radius-sm); overflow:hidden; }
.saved-strip span{ width:28px; height:28px; display:block; }
.btn-x{
  min-height:44px; min-width:44px; padding: 0 var(--s-4); font: inherit; font-size:.85rem; font-weight:700;
  background: var(--paper-2); border:2px solid var(--ink); border-radius: var(--radius-pill); cursor:pointer;
}
.btn-x:hover{ background: var(--pink); }

.hint{ font-size:.88rem; color: var(--ink-2); margin-top: var(--s-3); }

/* ============================================================
   Printable palette card
   Hidden on screen; in print it replaces the page entirely, so
   "Save as PDF" in the browser's print dialog gives a clean sheet
   rather than a screenshot of the app. No PDF library needed.
   ============================================================ */
.palette-card{ display:none; }

.palette-card .pc-head{ border-bottom: 3px solid #000; padding-bottom: 10px; margin-bottom: 18px; }
.palette-card .pc-head h2{ font-size: 26pt; margin: 0 0 4px; }
.palette-card .pc-head p{ font-size: 10pt; color:#333; margin: 0; }
.palette-card .pc-table{ width:100%; border-collapse: collapse; min-width:0; }
.palette-card .pc-table th{
  text-align:left; font-size: 9pt; text-transform:uppercase; letter-spacing:.08em;
  border-bottom: 2px solid #000; padding: 6px 10px 6px 0;
}
.palette-card .pc-table td{ padding: 12px 10px 12px 0; border-bottom: 1px solid #bbb; font-size: 11pt; vertical-align: middle; }
.palette-card .pc-sw{
  display:inline-block; width: 34px; height: 34px; vertical-align: middle;
  margin-right: 10px; border: 1px solid #000;
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.palette-card .pc-role{ font-size: 9pt; color:#555; }
.palette-card .num{ font-family:"DM Mono", monospace; }
.palette-card .pc-note{ margin-top: 18px; font-size: 9pt; color:#444; }

@media print{
  /* keep the ink in — swatches are the whole point of this sheet */
  *{ -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }
  .site-header, .site-footer, .skip, main > section, .nav-toggle, .mobile-nav{ display:none !important; }
  body{ background:#fff !important; color:#000 !important; font-size: 11pt; }
  .palette-card{ display:block !important; padding: 0; }
  /* no @page here — assets/js/print-export.js injects one matching the
     chosen paper, and a second rule fights it over margins. */
}

/* ---------- author block (About) -------------------------------------
   Sits OUTSIDE .prose: a photo column plus text will not fit inside the
   68ch reading measure without squeezing the text to ~40 characters. */
.author-block{ max-width: 880px; margin-block: var(--s-8); }
.author-block h2{ margin-bottom: var(--s-5); }

.author{ display:grid; gap: var(--s-5); align-items:start; }
@media (min-width: 640px){
  .author{ grid-template-columns: 240px 1fr; gap: var(--s-6); }
}
/* if the photo file is missing, collapse to one column rather than
   leaving an empty gutter and a squeezed text column */
.author.no-photo{ grid-template-columns: 1fr; }
.author.no-photo figure{ display:none; }

/* Circular portrait with an offset accent disc behind it — the same
   offset-shape idea as the logo and the hero glass sheets. */
.author figure{
  margin:0; position:relative;
  width: min(220px, 62vw);
}
.author figure::before{
  content:""; position:absolute; inset:0; z-index:0;
  border-radius:50%;
  background: var(--marigold);
  border: var(--border);
  transform: translate(11px, 11px);
}
.author img{
  position:relative; z-index:1;
  display:block; width:100%; height:auto;
  aspect-ratio: 1 / 1; border-radius: 50%;
  object-fit: cover; object-position: 50% 20%;   /* keep the face centred, not the shirt */
  border: var(--border); box-shadow: none;
  background: var(--paper-2);
}

.author-body > :first-child{ margin-top:0; }
.author-body p{ margin-bottom: var(--s-4); }
.author-body p:last-child{ margin-bottom:0; }

/* ============================================================
   Calculator tools — fields, answer lists, scale diagrams
   ============================================================ */
/* display:flex on these beats the browser's default [hidden]{display:none},
   so anything hidden with the hidden attribute stays visible unless this
   rule exists. Caught it with shape-specific fields showing on every shape. */
[hidden]{ display: none !important; }

.field-row{ display:flex; flex-wrap:wrap; gap: var(--s-4); }
.field{ flex:1 1 130px; min-width:0; }
.field-narrow{ flex:0 1 130px; }
.field label, .field-label{ display:block; font-weight:600; font-size:.9rem; margin-bottom: var(--s-2); }
.field input, .field select{
  width:100%; min-height:48px; padding: var(--s-2) var(--s-3);
  font: inherit; font-size:1rem;
  background: var(--white); color: var(--ink);
  border: var(--border); border-radius: var(--radius-sm);
}
.field input:focus-visible, .field select:focus-visible{
  outline: 3px solid var(--marigold-ink); outline-offset: 2px;
}

.answer-list{ list-style:none; margin:0; padding:0; }
/* a plain numbered list inside a panel — the prose rules only apply
   inside .prose, and a panel is not prose */
.prose-list{ margin: var(--s-4) 0 0; padding-left: var(--s-5); }
.prose-list li{ margin-bottom: var(--s-3); line-height:1.55; }

.answer-list li{
  padding: var(--s-4) 0; border-bottom: 2px solid var(--line);
}
.answer-list li:first-child{ padding-top:0; }
.answer-list li:last-child{ border-bottom:none; padding-bottom:0; }
.a-label{ display:block; font-size:.8rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color: var(--ink-2); }
.a-value{
  display:block; margin-top:2px;
  font-family:"Instrument Serif",Georgia,serif; font-weight:400;
  font-size: clamp(1.5rem, 3vw, 2rem); line-height:1.1;
  font-feature-settings:"tnum" 1;
}
.a-note{ display:block; margin-top:4px; font-size:.9rem; color: var(--ink-2); }

.stringer-svg{ width:100%; height:auto; display:block; }
.sd-piece{ fill: #EDEBF7; stroke: var(--sheet-line); stroke-width: 2; }
.sd-lines line{ stroke: var(--teal-ink); stroke-width: 2; stroke-linecap: round; }

.link-btn{
  background:none; border:0; padding:0; font:inherit; font-weight:600;
  color: var(--accent-ink); text-decoration:underline; text-underline-offset:3px;
  text-decoration-thickness:2px; cursor:pointer;
}
.link-btn:hover{ text-decoration-thickness:3px; }

/* ---------- cutting layout diagram ----------------------------------- */
.cut-svg{ width:100%; height:auto; display:block; }
.cut-sheet{ fill: #EDEBF7; stroke: var(--sheet-line); stroke-width: 2; }
.cut-piece{ fill: var(--teal); stroke: var(--sheet-line); stroke-width: 1.5; }

/* a disclosure for controls most people never need to touch */
.panel details > summary{
  cursor:pointer; font-weight:600; font-size:.9rem; color: var(--ink-2);
  padding: var(--s-2) 0; list-style:none;
}
.panel details > summary::-webkit-details-marker{ display:none; }
.panel details > summary::before{ content:"\25B8\00a0"; display:inline-block; transition: transform .15s; }
.panel details[open] > summary::before{ transform: rotate(90deg); }
.panel details > summary:focus-visible{ outline: 3px solid var(--marigold-ink); outline-offset: 3px; border-radius: 4px; }

/* plain-language summary above the numbers */
.answer-summary{
  margin: 0 0 var(--s-5);
  padding: var(--s-4);
  background: var(--paper-2);
  border: var(--border); border-radius: var(--radius-sm);
  font-size: 1.05rem; line-height: 1.55;
}
.answer-summary strong{ font-weight: 700; }

/* ============================================================
   Template Maker
   Templates print at TRUE SIZE: each SVG carries width/height
   in millimetres. Do not put width:100% on .tmpl in print, or
   the whole point of the tool is lost.
   ============================================================ */
.print-only{ display:none; }
/* Layout kept OUT of @media print deliberately: if it only existed there,
   there would be no way to see what the printed page will look like. */
.print-cal{ margin-bottom: 8mm; }
.print-cal p{ max-width: 150mm; margin: 3mm 0 0; line-height:1.4; font-size:.85rem; }
.print-items{ display:flex; flex-wrap:wrap; gap: 4mm; align-items:flex-start; }

/* The preview stands for a sheet of paper or a light table, and its cut
   lines are drawn dark so they can be printed. It therefore stays LIGHT
   in dark mode — otherwise dark lines sit on a dark ground and measure
   1.07:1, which is exactly what happened on the first pass. */
.preview-frame{
  background: var(--sheet); color: var(--sheet-line);
  border: var(--border); border-radius: var(--radius-sm);
  padding: var(--s-5); display:flex; justify-content:center; align-items:center;
  overflow:auto;
}
/* on screen only, scale the template down to fit the panel */
.tmpl-preview{ max-width:100%; height:auto; }

/* not scoped to .tmpl on purpose — the calibration box uses them too, and a
   missing fill:none turns a "box" into a solid black rectangle */
.t-cut{ fill:none; stroke:#16111C; stroke-width:0.4; }
.t-guide{ fill:none; stroke:#16111C; stroke-width:0.25; stroke-dasharray:2 1.5; }
.t-allow{ fill:none; stroke:#16111C; stroke-width:0.3; stroke-dasharray:3 2; opacity:.65; }

@media print{
  *{ -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }
  .no-print, .site-header, .site-footer, .skip, .nav-toggle, .mobile-nav{ display:none !important; }
  body{ background:#fff !important; color:#000 !important; margin:0; }
  .print-only{ display:block !important; }
  /* page size is owned by assets/js/print-export.js, which injects an
     @page rule matching the chosen paper. A second @page here fights it. */

  .print-cal p{ font-size: 9pt; }
  .print-item{ break-inside: avoid; page-break-inside: avoid; }
  /* true size — no scaling of any kind */
  .tmpl{ max-width:none !important; height:auto; }
}

.tmpl .t-marks line{ stroke:#16111C; stroke-width:0.5; }
@media print{
  .print-tile{ page-break-after: always; break-after: page; }
  /* no break after the final tile, or the printer emits a trailing blank */
  .print-tile:last-child{ page-break-after: auto; break-after: auto; }
  .print-items > .print-item:last-child{ page-break-after: auto; break-after: auto; }
  .tile-label{ font-size: 8pt; margin: 2mm 0 0; color:#000; line-height:1.2; }
  /* a tile must never be allowed to split across two sheets */
  .print-tile, .print-item{ break-inside: avoid; page-break-inside: avoid; overflow: hidden; }
}

/* pattern maker: outer boundary drawn heavier than the internal cuts */
.t-outer{ fill:none; stroke:#16111C; stroke-width:0.9; }

/* pattern maker palette + cut list swatches */
.cl-sw{ display:inline-block; width:14px; height:14px; border:1px solid var(--ink); border-radius:3px;
        vertical-align:-2px; margin-right:6px; }
.pal-list{ list-style:none; margin:0; padding:0; display:grid; gap:var(--s-3); }
.pal-item{ display:flex; gap:var(--s-3); align-items:flex-start; font-size:.92rem; }
.pal-sw{ width:34px; height:34px; flex:none; border:2px solid var(--ink); border-radius:var(--radius-sm); }
.swatch-picker{ display:flex; flex-wrap:wrap; gap:6px; max-height:210px; overflow:auto;
                border:var(--border); border-radius:var(--radius-sm); padding:var(--s-3);
                background:var(--white); }
.sw-btn{ width:30px; height:30px; border:2px solid var(--ink); border-radius:6px; cursor:pointer; padding:0; }
.sw-btn[aria-pressed="true"]{ outline:3px solid var(--marigold-ink); outline-offset:2px; }

/* panel outline drawn over the clipped composition */
.t-edge{ fill:none; stroke:#16111C; stroke-width:1.1; }

/* curve maker: numbered pieces on the printed template */
.pc-num{ font-family:"DM Mono",monospace; font-size:3px; fill:#16111C; text-anchor:middle;
         dominant-baseline:middle; }
@media print{ .pc-num{ font-size:3.2px; } }

/* ============================================================
   Tool page layout: controls left, preview pinned right,
   results in their own block underneath.

   The preview must stay visible while the controls are adjusted.
   A sticky element is bounded by its CONTAINING BLOCK, so the
   results cannot be siblings after it — it would travel down
   over them, which is exactly what happened when this was tried
   with display:contents (the containing block became the whole
   grid rather than the top row).

   So the right-hand column holds ONLY the preview. Being a grid
   item it stretches to the height of the tall controls column,
   which gives the sticky element room to travel, and there is
   nothing after it to overlap. The results sit outside the grid
   in .tool-results, full width — which the piece tables needed.
   ============================================================ */
@media (min-width: 980px){
  /* .tool-layout sets align-items:start, which leaves this column only as
     tall as the preview — and a sticky element with no taller ancestor has
     nowhere to travel, so it never pins. Stretch it to the row height. */
  .tool-layout > div:last-child{ align-self: stretch; }

  .tool-layout > div:last-child > .sticky-preview{
    position: sticky;
    top: calc(68px + var(--s-4));   /* clears the sticky site header */
  }
}

/* On a phone the two columns stack, and the preview is the SECOND one — so
   it landed after every control panel, nearly 4000px down. You could move a
   slider and never see what it did. Put the preview first and pin it, so the
   controls scroll underneath the thing they are changing. Multi-panel
   previews (Stringer Blocks has two) scroll inside the pinned box. */
@media (max-width: 979px){
  /* FLEX, not the stacked grid. A sticky element can only travel inside its
     own containing block: as a grid item that is just its own row, so it
     scrolled away immediately. As a flex item the containing block is the
     whole column, so it can stay pinned past all the controls. */
  .tool-layout{ display: flex; flex-direction: column; align-items: stretch; }
  .tool-layout > div:last-child{
    order: -1;
    position: sticky;
    top: calc(56px + var(--s-2));     /* clears the sticky site header */
    z-index: 5;
    max-height: 46vh;
    overflow: auto;
    background: var(--paper);          /* controls must not show through */
    padding-bottom: var(--s-2);
  }
  .sticky-preview .tmpl-preview,
  .sticky-preview .stringer-svg,
  .sticky-preview .cut-svg{ max-height: 32vh; }
  .sticky-preview .preview-frame{ max-height: 36vh; }
}

.tool-results{ margin-top: var(--s-5); }
.tool-results > .panel + .panel{ margin-top: var(--s-5); }

/* cap the artwork so a tall panel cannot outgrow the viewport */
.sticky-preview .tmpl-preview,
.sticky-preview .stringer-svg,
.sticky-preview .cut-svg{ max-height: 56vh; width: auto; margin-inline: auto; }
.sticky-preview .preview-frame{ max-height: 62vh; overflow: auto; }

/* ---------- frit preview ------------------------------------------ */
/* Swatches are glass, so their edge is --on-bright and never inverts.
   44px because the brand sets touch targets there; the older .sw-btn
   swatches are 30px and should be brought up to this when next touched. */
.frit-grid{ display:flex; flex-wrap:wrap; gap: var(--s-2); margin-top: var(--s-4);
  max-height: 300px; overflow-y:auto; padding: 4px; }
.frit-sw{ width:44px; height:44px; flex:none; padding:0; cursor:pointer;
  border:2px solid var(--on-bright); border-radius: var(--radius-sm); }
.frit-sw[aria-pressed="true"]{ outline:3px solid var(--outline); outline-offset:2px; }
.frit-sw:focus-visible{ outline:3px solid var(--outline); outline-offset:3px; }
.frit-sw[disabled]{ opacity:.4; cursor:not-allowed; }

.frit-chosen{ list-style:none; margin: var(--s-4) 0 0; padding:0; display:grid; gap: var(--s-2); }
.frit-chosen li{ display:flex; align-items:center; gap: var(--s-3); }
.frit-chosen .frit-chip{ width:28px; height:28px; flex:none; border-radius:6px;
  border:2px solid var(--on-bright); }
.frit-chosen .frit-name{ flex:1; min-width:0; font-size:.92rem; line-height:1.3; }
.frit-chosen .frit-name .style-no{ color: var(--ink-2); }
.frit-chosen .frit-act{ min-height:44px; min-width:44px; padding: 0 var(--s-3); font: inherit;
  font-size:.85rem; font-weight:600; background: var(--surface); color: var(--ink);
  border:2px solid var(--outline); border-radius: var(--radius-pill); cursor:pointer; }
.frit-chosen .frit-act[disabled]{ opacity:.35; cursor:default; }

.frit-frame{ padding:0; overflow:hidden; }
.frit-frame canvas{ display:block; width:100%; height:auto; }


/* a source photo shown small beside the palette it produced. .frit-photo
   is the same thing under the frit preview; .src-photo is the generic one. */
.src-photo{ margin: var(--s-4) 0 0; }
.src-photo img{ display:block; width:100%; max-width:260px; height:auto;
  border: var(--border); border-radius: var(--radius-sm); }
.src-photo figcaption{ margin-top: var(--s-2); font-size:.85rem; color: var(--ink-2); }

/* the source photo, shown under the frit version so they can be compared */
.frit-photo{ margin: var(--s-4) 0 0; }
.frit-photo img{ display:block; width:100%; height:auto;
  border: var(--border); border-radius: var(--radius-sm); }
.frit-photo figcaption{ margin-top: var(--s-2); font-size:.85rem; color: var(--ink-2); }
.frit-match{ display:inline-flex; gap:4px; vertical-align:-3px; margin-right:6px; }
.frit-match span{ width:16px; height:16px; border-radius:4px; border:1px solid var(--on-bright); }
