/* ============================================================
   tt-com.css — the ONE stylesheet for tomasettitech.com
   Identity: concept 1 "framework cadence" (LOCKED 2026-10-02).
   Source of truth:
     docs/design/concepts-2026-10-02/concept-1-framework-cadence.html
   Builder contract:
     docs/design/com-site-conventions.md
   Craft floor held invisibly: docs/design/repair-site-craft-floor.md
   (§7 structural discipline transfers; the purple family is the
   exception Tj explicitly claimed for the .com brand.)

   ZERO EXTERNAL DEPS: system font stacks, no CDN, no webfonts.

   Contrast, computed (WCAG 2.x) — decisions written down, not luck:
     ink #16131d on canvas #f8f8f8 ........ 17.3:1
     ink-soft #3f3a4d on canvas ........... 10.3:1
     muted #6b6577 on canvas .............. 5.3:1  (small print)
     accent #6036b8 on canvas ............. 7.3:1  (links/labels)
     white #fff on accent ................. 7.7:1  (button text)
     white on accent-deep #4d2a99 ......... 10.0:1 (button hover)
     lilac #c9b4f2 on ink-band #16131d .... 9.9:1  (dark band text)
     #7a5cc7 on ink-band = 3.7:1 → decoration only, never text.

   Accent budget: ONE accent (purple #6036b8) owns CTA fills, links,
   focus rings, active states. Amber #e8a23d is the warm accent used
   SPARINGLY (dots, star flourishes) — never chrome, never text.
   There is no highlighter treatment: concept 1 has none.

   MOTION IS GATE-FIRST: animated rules exist only under html.anim
   (a class added by JS only when prefers-reduced-motion does not
   match). No JS = no gate = the plain, fully visible page. A
   prefers-reduced-motion media query backstops the rest.
   ============================================================ */

/* ---- tokens ---- */
:root{
  --canvas:#f8f8f8; --canvas-deep:#f1f1f3; --surface:#ffffff;
  --ink:#16131d; --ink-soft:#3f3a4d; --muted:#6b6577;
  --accent:#6036b8; --accent-deep:#4d2a99; --accent-mid:#7a5cc7;
  --accent-tint:rgba(96,54,184,.08); --accent-tint2:rgba(96,54,184,.05);
  --lilac:#c9b4f2; /* dark-band text tier: 9.9:1 on --ink */
  --amber:#e8a23d; --amber-soft:rgba(232,162,61,.16);
  --line:rgba(22,19,29,.14); --line-strong:rgba(22,19,29,.26);
  --lift:0 10px 30px rgba(22,19,29,.10); /* the one shadow token */
  --sans:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
  --mono:ui-monospace,"Cascadia Mono","SF Mono",Consolas,monospace;
  --shell:1180px; --reading:640px;
}

/* ---- base ---- */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{margin:0;background:var(--canvas);color:var(--ink);font:16px/1.65 var(--sans);-webkit-font-smoothing:antialiased}
img{display:block;max-width:100%;height:auto}
a{color:var(--accent)}
::selection{background:var(--accent);color:#fff}
:focus-visible{outline:3px solid rgba(96,54,184,.4);outline-offset:2px;border-radius:4px}

/* ---- type: two fonts, two jobs. Sans = everything human; mono is
   uppercase micro-labels only (+0.08–0.12em). Machine truth = mono. ---- */
h1,h2,h3{letter-spacing:-.03em;line-height:1.05;font-weight:700;color:var(--ink)}
h2{font-size:clamp(1.9rem,4.5vw,2.9rem)}
h3{font-size:1.2rem;letter-spacing:-.015em;line-height:1.3}
p{margin:0}
.kicker{font:.72rem/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;font-weight:600;color:var(--accent);margin-bottom:14px}
.lede{font-size:1.12rem;line-height:1.65;color:var(--ink-soft)}
.display-xl{font-size:clamp(2.4rem,6vw,4.4rem);letter-spacing:-.03em;line-height:1.05;font-weight:700}
/* .caps opts a display line into uppercase; concept 1's hero is
   sentence-case by default — uppercase is a per-page choice. */
.caps{text-transform:uppercase;letter-spacing:-.01em}
.mono-label{font:.72rem/1.5 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.accent-word{color:var(--accent)}

/* ---- layout: one container width per job. Shell 1180, reading 640.
   Section rhythm is one number per role: 88px desktop, 56px mobile. ---- */
.wrap{max-width:var(--shell);margin:0 auto;padding:0 28px}
.read{max-width:var(--reading);margin-left:auto;margin-right:auto}
.section{padding:88px 0}
@media (max-width:640px){.section{padding:56px 0}}

/* ---- honesty banner strip (top of every page, before the nav) ---- */
.banner{font:11px/1.5 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--muted);text-align:center;padding:8px 16px;background:var(--canvas-deep);border-bottom:1px solid var(--line)}
.banner b{color:var(--accent);font-weight:600}

/* ---- nav: wordmark left, links right. Mobile collapse keeps the
   wordmark + the one bordered utility item (≤700px); links reopen on
   any pointer that can reach them — no JS hamburger in v1. ---- */
.nav{position:sticky;top:0;z-index:50;background:rgba(248,248,248,.92);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-bottom:1px solid var(--line)}
.nav-in{max-width:var(--shell);margin:0 auto;padding:0 28px;min-height:64px;display:flex;align-items:center;gap:26px}
.wordmark{font-weight:700;font-size:1.05rem;letter-spacing:-.02em;color:var(--ink);text-decoration:none}
.wordmark em{font-style:normal;color:var(--accent)}
.nav-links{display:flex;gap:4px;margin-left:auto;align-items:center}
.nav-links a{display:inline-flex;align-items:center;font-size:.92rem;font-weight:500;color:var(--ink-soft);text-decoration:none;padding:10px 12px;border-radius:8px;min-height:44px}
.nav-links a:hover{color:var(--accent);background:var(--accent-tint2)}
.nav-links a.util{border:1px solid var(--line-strong);margin-left:8px}
.nav-links a.util:hover{border-color:var(--accent)}
@media (max-width:700px){.nav-links a:not(.util){display:none}}
@media (max-width:700px){.nav-links a.util{min-height:44px}}

/* ---- buttons: 48px tap floor. Solid purple + outline ghost; the
   only two button voices on the site. ---- */
.button{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:12px 24px;border-radius:10px;font-family:var(--sans);font-weight:600;font-size:1rem;letter-spacing:-.01em;text-decoration:none;white-space:nowrap;border:1px solid transparent;cursor:pointer}
.button-primary{background:var(--accent);color:#fff}
.button-primary:hover{background:var(--accent-deep)}
.button-ghost{background:transparent;color:var(--ink);border-color:var(--line-strong)}
.button-ghost:hover{border-color:var(--accent);color:var(--accent)}
html.anim .button{transition:background .15s,color .15s,border-color .15s,transform .08s}
html.anim .button:active{transform:translateY(1px) scale(.99)}

/* ---- hero: centered display block, full-bleed render below ---- */
.hero{padding:72px 0 0;text-align:center}
.hero h1{font-size:clamp(2.4rem,6vw,4.4rem);max-width:15ch;margin:0 auto 18px}
.hero .lede{max-width:52ch;margin:0 auto 30px}
.hero-ctas{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-bottom:10px}
.hero-render{margin:34px 0 0}
.hero-render img{width:100%;border-radius:0}
.hero-render figcaption{font:11px/1.6 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--muted);padding:14px 28px 0;max-width:var(--shell);margin:0 auto;text-align:left}

/* ---- pill / badge: mono-caps chip, 1px border, no fill. The
   in-development mark and honesty labels are pills, never big. ---- */
.pill{display:inline-flex;align-items:center;gap:6px;font:.68rem/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-soft);border:1px solid var(--line-strong);border-radius:99px;padding:5px 10px;text-decoration:none;white-space:nowrap}
.pill-solid{background:var(--accent);border-color:var(--accent);color:#fff}
.pill:hover{border-color:var(--accent);color:var(--accent)}
.pill-solid:hover{background:var(--accent-deep);border-color:var(--accent-deep);color:#fff}

/* ---- amber dot: the warm accent, spent like money. Flourish only —
   never a link color, never a fill on chrome. ---- */
.dot{display:inline-block;width:16px;height:16px;border-radius:50%;background:radial-gradient(circle at 38% 32%,#ffd894,var(--amber) 62%,#b06f1e);box-shadow:0 0 0 3px var(--amber-soft);vertical-align:middle}
html.anim .dot{transition:transform .25s cubic-bezier(.34,1.56,.64,1)}
html.anim .dot:hover{transform:scale(1.25)}

/* ---- marquee: the ONE ambient loop, our words. Gate-first: the
   animation exists only under html.anim; reduced-motion users and
   no-JS visitors get the same words as a static wrapped line. ---- */
.marquee{overflow:hidden;border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--surface);padding:22px 0;margin-top:56px}
.marquee-track{display:flex;gap:0;width:max-content;white-space:nowrap}
.marquee-track span{font-size:clamp(1.5rem,3.2vw,2.4rem);font-weight:700;letter-spacing:-.025em;color:var(--ink);padding-right:.6em}
.marquee .star{color:var(--amber);font-weight:400}
html.anim .marquee-track{animation:slide 36s linear infinite}
.marquee:hover .marquee-track{animation-play-state:paused}
@keyframes slide{to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){.marquee-track{animation:none !important;flex-wrap:wrap;white-space:normal;width:auto;padding:0 28px}}

/* ---- product card: screenshot on top, words below. Hairline card,
   hover flips the border purple and lifts — the one card hover on
   the site (transition gated). Image slot keeps a 16/10 frame so
   mixed screenshots align. ---- */
.product-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:20px}
.product-card{display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--line);border-radius:14px;overflow:hidden;text-decoration:none;color:inherit}
.product-card:hover{border-color:var(--accent)}
html.anim .product-card{transition:border-color .15s,transform .15s,box-shadow .15s}
html.anim .product-card:hover{transform:translateY(-2px);box-shadow:var(--lift)}
.product-shot{aspect-ratio:16/10;object-fit:cover;object-position:top;width:100%;background:var(--canvas-deep);border-bottom:1px solid var(--line)}
.product-body{padding:22px 26px;display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.product-body h3{margin:0}
.product-body p{color:var(--ink-soft);font-size:.95rem}
.product-link{font-weight:600;color:var(--accent);white-space:nowrap}

/* ---- software band: the honest one-liner strip (canvas-deep) ---- */
.software{border-top:1px solid var(--line);padding:56px 0;background:var(--canvas-deep)}
.soft-card{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px;justify-content:space-between;background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:22px 26px}
.soft-card p{color:var(--ink-soft);max-width:56ch}
.soft-card p b{color:var(--ink)}
.soft-card a{font-weight:600;white-space:nowrap}

/* ---- dark band (mission): ink background, lilac text tier.
   accent-mid on ink is 3.7:1 — decoration only; the kicker reads in
   lilac (9.9:1). ---- */
.band-ink{background:var(--ink);color:#fff;padding:88px 0}
@media (max-width:640px){.band-ink{padding:56px 0}}
.band-ink .kicker{color:var(--lilac)}
.band-ink h2{max-width:22ch;margin:0 0 22px;color:#fff}
.band-ink p{max-width:60ch;color:var(--lilac);font-size:1.05rem}
.band-ink .sign{margin-top:26px;font:12px/1.6 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:rgba(201,180,242,.75)}

/* ---- forms / waitlist: 48px floors, purple focus ring. One input
   voice: surface fill, hairline-strong border, radius 10. ---- */
.field{display:flex;flex-direction:column;gap:6px}
.field label{font:.72rem/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.input,.waitlist input[type="email"]{min-height:48px;padding:12px 14px;border-radius:10px;border:1px solid var(--line-strong);background:var(--surface);color:var(--ink);font:1rem/1.4 var(--sans);width:100%}
.input:focus-visible,.waitlist input[type="email"]:focus-visible{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-tint)}
.waitlist{display:flex;gap:10px;flex-wrap:wrap;align-items:stretch;max-width:460px}
.waitlist input[type="email"]{flex:1 1 220px}
.form-note{font-size:.85rem;color:var(--muted)}
.form-error{font-size:.88rem;color:var(--accent-deep)}

/* ---- footer ---- */
footer{border-top:1px solid var(--line);background:var(--canvas-deep);padding:56px 0 32px}
.foot-grid{display:grid;grid-template-columns:2fr 1fr 1fr;gap:32px}
@media (max-width:700px){.foot-grid{grid-template-columns:1fr}}
.foot-grid h3{font:.72rem/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin:0 0 12px}
.foot-grid ul{list-style:none;margin:0;padding:0}
.foot-grid li{margin-bottom:4px}
.foot-grid a{display:inline-flex;align-items:center;min-height:44px;color:var(--ink-soft);text-decoration:none;font-size:.94rem}
.foot-grid a:hover{color:var(--accent);text-decoration:underline}
.foot-brand{font-weight:700;font-size:1.2rem;letter-spacing:-.02em;margin:0 0 8px}
.foot-brand em{font-style:normal;color:var(--accent)}
.foot-tag{color:var(--ink-soft);max-width:38ch}
.fineprint{margin-top:40px;padding-top:20px;border-top:1px solid var(--line);color:var(--muted);font-size:.85rem;display:flex;flex-wrap:wrap;gap:8px 24px;justify-content:space-between}

/* ---- build additions (task P3, 2026-10-02): the patterns the four
   build pages needed that the kit did not have yet. Same tokens, same
   gate-first motion rules, same accent budget. Nothing here redefines
   an existing class. ---- */

/* in-section render figures + the deck's mono-caps caption pattern:
   `design render · <subject> · not a product photo · nothing ordered` */
.render{margin:0}
.render img{width:100%}
.render figcaption{font:11px/1.6 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--muted);padding:10px 2px 0;text-align:left}

/* figure rows: two-up, three-up, four-up. Rows collapse toward one
   column as width shrinks; the four-up keeps two columns on phones so
   colorway tiles stay tile-sized. */
.grid-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}
.grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px}
.grid-4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:24px}
@media (max-width:860px){.grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:640px){.grid-2{grid-template-columns:1fr}.grid-3{grid-template-columns:1fr}.grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-2,.grid-3,.grid-4{gap:16px}}

/* copy + figure split (designed-to-open, thermal honesty sections) */
.open-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr);gap:40px;align-items:center}
@media (max-width:900px){.open-grid{grid-template-columns:1fr;gap:28px}}
.open-copy p{margin-top:16px;color:var(--ink-soft)}

/* centered section head: kicker + h2 + lede in one column */
.sec-head{text-align:center;max-width:760px;margin:0 auto 34px}
.sec-head .lede{margin-top:16px}

/* the face flip (from concept 1, made class-based so a page may carry
   one; transitions gated under html.anim like everything else) */
.flip{background:var(--surface);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.flip-head{text-align:center;margin-bottom:26px}
.stage{position:relative;max-width:980px;margin:0 auto;aspect-ratio:1600/1100;background:var(--canvas);border:1px solid var(--line);border-radius:16px;overflow:hidden}
.stage img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0}
.stage img.on{opacity:1;position:relative}
html.anim .stage img{transition:opacity .45s cubic-bezier(.22,1,.36,1)}
.face-caption{position:absolute;left:0;right:0;bottom:0;padding:14px 18px;text-align:center;font:12px/1.5 var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft);background:linear-gradient(transparent,rgba(248,248,248,.92) 40%);margin:0}
.flip-ctl{display:flex;justify-content:center;align-items:stretch;gap:0;margin:22px auto 0;border:1px solid var(--line-strong);border-radius:99px;width:max-content;max-width:100%;overflow:hidden;background:var(--surface)}
.flip-ctl button{min-height:48px;min-width:44px;padding:12px 20px;font:600 .95rem/1.2 var(--sans);letter-spacing:-.01em;background:transparent;border:0;color:var(--ink-soft);cursor:pointer}
html.anim .flip-ctl button{transition:background .15s,color .15s}
.flip-ctl button:hover{color:var(--accent);background:var(--accent-tint2)}
.flip-ctl button[aria-pressed="true"]{background:var(--accent);color:#fff}
.flip-ctl .hinge{display:flex;align-items:center;padding:0 6px;background:transparent;border-left:1px solid var(--line);border-right:1px solid var(--line)}
.flip-ctl .hinge button{min-height:48px;width:56px;padding:0;display:flex;align-items:center;justify-content:center;border-radius:0}
html.anim .hinge .dot{transition:transform .25s cubic-bezier(.34,1.56,.64,1)}
html.anim .hinge .dot:hover{transform:scale(1.25)}
.flip-note{text-align:center;color:var(--muted);font-size:.88rem;margin-top:16px}
@media (max-width:480px){.flip-ctl button{white-space:normal;padding:10px 12px;font-size:.82rem;line-height:1.2}.flip-ctl .hinge{padding:0 4px}.flip-ctl .hinge button{width:44px}}

/* home product-hero sequence: one full-width block per product line */
.seq{padding:88px 0}
.seq + .seq{border-top:1px solid var(--line)}
@media (max-width:640px){.seq{padding:56px 0}}
.sub-lines{margin-top:18px}
.sub-lines p{margin-top:6px;color:var(--ink-soft)}
.seq-ctas{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-top:24px}

/* the wall-i colorway caption row (a sentence, styled as a caption) */
.colorway-line{max-width:720px;margin:20px auto 0;text-align:center;color:var(--muted);font-size:.9rem;line-height:1.7}

/* two placement utilities the build pages share (no page-local CSS) */
.mx-auto{margin-left:auto;margin-right:auto}
.fit-stage{max-width:980px;margin-left:auto;margin-right:auto}

/* drag-to-spin turntable (stream page): poster-first, the 36 frames
   lazy-load on the first drag or arrow key (the JS never wires up under
   reduced motion, so those users keep the static poster). touch-action
   keeps vertical page scroll alive on touch; the interaction is
   horizontal-only. Same card voice as .stage: hairline border, 16px
   radius, canvas fill. */
.turntable{position:relative;cursor:grab;touch-action:pan-y;user-select:none;-webkit-user-select:none;border:1px solid var(--line);border-radius:16px;overflow:hidden;background:var(--canvas)}
.turntable.dragging{cursor:grabbing}
.turntable:focus-visible{outline:3px solid rgba(96,54,184,.4);outline-offset:3px}
.turntable img{pointer-events:none;width:100%}

/* the compiled loop beneath the widget: capped at the frames' native
   800px so it never upscales; same card voice, own controls only */
.spin-video{max-width:800px;margin:28px auto 0}
.spin-video video{display:block;width:100%;height:auto;background:var(--canvas);border:1px solid var(--line);border-radius:16px}
.spin-hint{text-align:center;color:var(--muted);font-size:.88rem;margin-top:16px}

/* ---- motion: ONE entrance family (reveal). Rules exist only under
   html.anim — no JS, no motion permission, no hidden content. ---- */
html.anim .rv{opacity:0;transform:translateY(14px)}
html.anim .rv.in{opacity:1;transform:none;transition:opacity .6s cubic-bezier(.22,1,.36,1),transform .6s cubic-bezier(.22,1,.36,1)}
@media (prefers-reduced-motion:reduce){
  html.anim .rv{opacity:1;transform:none;transition:none}
  *{animation:none !important;transition:none !important}
}
