/* ============================================================
   WarrFX member app — shared styles.

   Tokens are the same ones the marketing site uses, pasted from design-library/LAYOUT.md
   and MOTION.md. The app and the site are one product and must not drift apart; the
   mockup-only palette is left out because nothing here imitates XM's interface.

   Structure: the sign-up is genuinely a two-step sequence, and the second step is what
   unlocks posting, so the step rail is numbered. That numbering carries real information —
   it is not decoration.
   ============================================================ */
:root{
  --space-xs:.25rem; --space-s:.375rem; --space-sm:.5rem;
  --space-m:.75rem; --space-l:1.125rem; --space-xl:1.5rem;
  --section-s:2rem; --section-sm:2.5rem; --section-m:3.75rem;
  --section-l:5rem; --section-xl:7.5rem;

  /* Dark is the default, not a mode. WarrFX's own material is dark, traders read charts on
     dark, and this is a page people sit on for a while. Light is the alternative. */
  --ink:#f1f4ee;
  --ground:#07090a;
  --panel:#101512;
  --panel-2:#161d18;
  --line:rgba(241,244,238,.1);
  --line-strong:rgba(241,244,238,.18);
  --muted:#8b968d;
  --accent:#8dc143;
  --accent-ink:#0c1108;
  --accent-dim:#5c7f2e;
  --accent-hover:#a0d456;
  --red:#e2554a;
  --red-ground:rgba(226,85,74,.09);
  --amber:#e0a233;
  --amber-ground:rgba(224,162,51,.09);
  --accent-ground:rgba(141,193,67,.09);

  /* Passed to TradingView, which cannot read CSS variables — its widgets are iframes on
     another origin and take a theme name plus literal colours at mount time. */
  --tv-theme:dark;

  --fs-xs:.75rem;   --lh-xs:1rem;      --tr-xs:0;
  --fs-sm:.875rem;  --lh-sm:1.25rem;   --tr-sm:0;
  --fs-base:1rem;   --lh-base:1.4;     --tr-base:0;
  --fs-lg:1.125rem; --lh-lg:1.4;       --tr-lg:0;
  --fs-xl:1.25rem;  --lh-xl:1.2;       --tr-xl:-.01em;
  --fs-2xl:1.5rem;  --lh-2xl:1.15;     --tr-2xl:-.01em;
  --fs-3xl:1.875rem;--lh-3xl:1.1;      --tr-3xl:-.02em;
  --fs-4xl:2.25rem; --lh-4xl:1.05;     --tr-4xl:-.02em;

  --dur-state:150ms; --dur-ui:250ms; --dur-enter:400ms; --dur-hero:800ms;
  --ease:cubic-bezier(.25,.46,.45,.94);
  --ease-out:cubic-bezier(.19,1,.22,1);
  --ease-in:cubic-bezier(.4,0,1,1);
  --dist:16px;

  --font-display:'Space Grotesk',system-ui,sans-serif;
  --font-mono:'Roboto Mono',ui-monospace,monospace;

  --radius:4px;
  --field-h:2.875rem;
  --measure:34rem;
}
@media (min-width:768px){
  :root{
    --space-s:.5rem; --space-sm:.625rem; --space-m:.875rem;
    --space-l:1.125rem; --space-xl:1.625rem;
    --section-s:2.25rem; --section-sm:3.125rem; --section-m:4.375rem;
    --section-l:6.25rem; --section-xl:9.375rem;
  }
}
@media (min-width:1024px){
  :root{
    --space-sm:.75rem; --space-m:1rem; --space-l:1.25rem; --space-xl:1.75rem;
    --section-s:2.5rem; --section-sm:3.75rem; --section-m:5rem; --section-l:7.5rem;
  }
}
/* ------------------------------------------------------------------ light
   The light palette is designed, not inverted. The brand green is unreadable as text on a
   pale ground — #8dc143 on near-white is about 2:1 — so light gets a darker green of its
   own, and the neutrals are tinted very slightly toward the brand hue rather than being
   flat grey. Only tokens are redefined here; no component rule ever names a colour.

   Three states, not two: an explicit choice stamps data-theme, and the default "system"
   setting stamps nothing, where prefers-color-scheme decides. */
/* Every literal colour in this file lives in the one :root block above, light included, and
   the two rules below only remap which set is in play. CSS has no way to share a token set
   between a media query and an attribute selector, and writing the hex twice is how the two
   themes drift apart — one gets a tweak and the other quietly does not. */
:root{
  --l-ink:#12160f;
  --l-ground:#f6f7f3;
  --l-panel:#ffffff;
  --l-panel-2:#eef0e9;
  --l-line:rgba(18,22,15,.12);
  --l-line-strong:rgba(18,22,15,.22);
  --l-muted:#5b6356;
  --l-accent:#4c6f22;
  --l-accent-ink:#ffffff;
  --l-accent-dim:#7fa049;
  --l-accent-hover:#3d5a1b;
  --l-red:#b3271c;
  --l-red-ground:rgba(179,39,28,.07);
  --l-amber:#8a5e0c;
  --l-amber-ground:rgba(138,94,12,.09);
  --l-accent-ground:rgba(76,111,34,.09);
}

@media (prefers-color-scheme: light){
  :root:not([data-theme="dark"]){
    --ink:var(--l-ink); --ground:var(--l-ground);
    --panel:var(--l-panel); --panel-2:var(--l-panel-2);
    --line:var(--l-line); --line-strong:var(--l-line-strong);
    --muted:var(--l-muted);
    --accent:var(--l-accent); --accent-ink:var(--l-accent-ink);
    --accent-dim:var(--l-accent-dim); --accent-hover:var(--l-accent-hover);
    --red:var(--l-red); --red-ground:var(--l-red-ground);
    --amber:var(--l-amber); --amber-ground:var(--l-amber-ground);
    --accent-ground:var(--l-accent-ground);
    --tv-theme:light;
  }
}
/* The explicit choice wins in both directions, so the toggle beats the operating system. */
:root[data-theme="light"]{
  --ink:var(--l-ink); --ground:var(--l-ground);
  --panel:var(--l-panel); --panel-2:var(--l-panel-2);
  --line:var(--l-line); --line-strong:var(--l-line-strong);
  --muted:var(--l-muted);
  --accent:var(--l-accent); --accent-ink:var(--l-accent-ink);
  --accent-dim:var(--l-accent-dim); --accent-hover:var(--l-accent-hover);
  --red:var(--l-red); --red-ground:var(--l-red-ground);
  --amber:var(--l-amber); --amber-ground:var(--l-amber-ground);
  --accent-ground:var(--l-accent-ground);
  --tv-theme:light;
}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
}

/* ---------------------------------------------------------------- base */
*{box-sizing:border-box; margin:0; padding:0;}
body{
  background:var(--ground); color:var(--ink);
  font-family:var(--font-display);
  font-size:var(--fs-base); line-height:var(--lh-base);
  -webkit-font-smoothing:antialiased;
  min-height:100vh;
}
a{color:var(--accent);}
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible{
  outline:2px solid var(--accent); outline-offset:2px;
}

.shell{
  max-width:var(--measure); margin:0 auto;
  padding:var(--section-s) var(--space-xl) var(--section-m);
}
/* Sign-up is a single column of questions and wants a narrow measure. A chart wants room. */
.shell.wide{max-width:72rem;}

/* ---------------------------------------------------------------- app nav */
.tabs{
  display:flex; gap:var(--space-xs);
  border-bottom:1px solid var(--line);
  margin-bottom:var(--section-s);
  overflow-x:auto; scrollbar-width:none;
}
.tabs::-webkit-scrollbar{display:none;}
.tabs a,.tabs span{
  padding:var(--space-m) var(--space-l);
  font-size:var(--fs-sm); line-height:var(--lh-sm); font-weight:500;
  color:var(--muted); text-decoration:none; white-space:nowrap;
  border-bottom:2px solid transparent; margin-bottom:-1px;
  transition:color var(--dur-state) var(--ease);
}
.tabs a:hover{color:var(--ink);}
.tabs a[aria-current="page"]{color:var(--ink); border-bottom-color:var(--accent);}
/* Tabs that are not built yet say so rather than looking broken when clicked. */
.tabs span{opacity:.45; cursor:default;}
.tabs span::after{
  content:"soon"; margin-left:var(--space-sm);
  font-family:var(--font-mono); font-size:.625rem; letter-spacing:.08em;
  text-transform:uppercase; border:1px solid var(--line-strong);
  border-radius:var(--radius); padding:.0625rem .25rem; vertical-align:middle;
}

/* ------------------------------------------------------------ post + news */
.stack{display:flex; flex-direction:column; gap:var(--space-xl);}

.post{
  background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius); padding:var(--space-xl);
}
.post h3{
  font-size:var(--fs-xl); line-height:var(--lh-xl); letter-spacing:var(--tr-xl);
  font-weight:700; margin-bottom:var(--space-sm); text-wrap:balance;
}
.post p{color:var(--muted); white-space:pre-wrap;}
.post .meta{
  display:flex; align-items:center; gap:var(--space-m); flex-wrap:wrap;
  margin-bottom:var(--space-m);
  font-family:var(--font-mono); font-size:var(--fs-xs); line-height:var(--lh-xs);
  letter-spacing:.04em; text-transform:uppercase; color:var(--muted);
}

/* Headlines link out to the publisher. Nothing here reproduces an article. */
.news{list-style:none;}
.news li{border-bottom:1px solid var(--line);}
.news a{
  display:block; padding:var(--space-l) 0; text-decoration:none; color:var(--ink);
  transition:color var(--dur-state) var(--ease);
}
.news a:hover{color:var(--accent);}
.news h4{font-size:var(--fs-base); line-height:var(--lh-base); font-weight:600; text-wrap:balance;}
.news .meta{
  margin-top:var(--space-s);
  font-family:var(--font-mono); font-size:var(--fs-xs); line-height:var(--lh-xs);
  color:var(--muted); letter-spacing:.04em;
}
.news p{margin-top:var(--space-sm); color:var(--muted); font-size:var(--fs-sm); line-height:var(--lh-sm);}

.empty{
  border:1px dashed var(--line-strong); border-radius:var(--radius);
  padding:var(--section-s) var(--space-xl); text-align:center;
  color:var(--muted); font-size:var(--fs-sm); line-height:var(--lh-sm);
}

/* ------------------------------------------------------- embedded widgets */
/* TradingView renders into these. A fixed height is set up front so the page does not
   jump when the widget finally paints. */
.widget{
  background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius); overflow:hidden; margin-bottom:var(--space-xl);
}
.widget-chart{height:32rem; position:relative;}

/* The chart eats wheel and touch events to zoom itself, so a reader scrolling the page over
   it gets stuck — worst on a phone, which is the primary viewport here. The chart stays
   inert behind this until it is deliberately tapped. */
.chart-guard{
  position:absolute; inset:0; z-index:2;
  display:grid; place-items:end center;
  padding-bottom:var(--space-l);
  cursor:pointer; background:transparent;
  border:0; width:100%;
}
.chart-guard span{
  background:var(--panel-2); border:1px solid var(--line-strong);
  border-radius:var(--radius); color:var(--ink);
  padding:var(--space-sm) var(--space-l);
  font-family:var(--font-mono); font-size:var(--fs-xs); line-height:var(--lh-xs);
  letter-spacing:.06em; text-transform:uppercase;
  transition:border-color var(--dur-state) var(--ease);
}
.chart-guard:hover span,.chart-guard:focus-visible span{border-color:var(--accent);}
.chart-guard[hidden]{display:none;}
/* No min-width. One was added on 2026-08-30 to "fix" a blank calendar on mobile; the blanking
   had nothing to do with width, and forcing a floor only made a phone scroll sideways for no
   reason. A cold browser at 390px renders the calendar fully — four columns, times, forecast
   and previous — see tv-probe.mjs. */
.widget-calendar{height:28rem;}
.widget-ticker{height:4.5rem;}
@media (min-width:768px){ .widget-chart{height:38rem;} }

/* Shown when a widget never arrives. A blank card reads as a broken page; this says what
   happened and offers the one thing that usually helps. */
.widget-fallback{
  height:100%; display:grid; place-items:center; gap:var(--space-m);
  padding:var(--space-xl); text-align:center;
}
.widget-fallback p{color:var(--muted); font-size:var(--fs-sm); line-height:var(--lh-sm); max-width:24rem;}
.widget-fallback button{
  background:transparent; color:var(--ink);
  border:1px solid var(--line-strong); border-radius:var(--radius);
  padding:var(--space-sm) var(--space-l); cursor:pointer;
  font-family:var(--font-mono); font-size:var(--fs-xs); letter-spacing:.06em;
  text-transform:uppercase;
}
.widget-fallback button:hover{border-color:var(--accent); color:var(--accent);}

.section-title{
  font-size:var(--fs-lg); line-height:var(--lh-lg); font-weight:700;
  margin-bottom:var(--space-l);
}

/* ---------------------------------------------------------------- masthead */
.masthead{
  display:flex; align-items:center; gap:var(--space-m);
  margin-bottom:var(--section-s);
}
.masthead img{width:2.25rem; height:2.25rem; border-radius:50%; display:block;}
.wordmark{
  font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  font-size:var(--fs-sm); line-height:var(--lh-sm);
}
.wordmark em{color:var(--accent); font-style:normal;}

/* Pushed to the far end of the masthead. */
.theme-toggle{
  margin-left:auto;
  display:inline-flex; align-items:center; gap:var(--space-sm);
  background:transparent; color:var(--muted);
  border:1px solid var(--line-strong); border-radius:var(--radius);
  padding:var(--space-sm) var(--space-m);
  font-family:var(--font-mono); font-size:var(--fs-xs); line-height:var(--lh-xs);
  letter-spacing:.06em; text-transform:uppercase; cursor:pointer;
  transition:color var(--dur-state) var(--ease), border-color var(--dur-state) var(--ease);
}
.theme-toggle:hover{color:var(--ink); border-color:var(--muted);}
.theme-toggle svg{width:.875rem; height:.875rem; fill:currentColor;}
/* One icon is shown at a time, chosen by the theme actually in force — so it stays correct
   when the operating system decides rather than the button. */
.theme-toggle .to-dark{display:none;}
.theme-toggle .to-light{display:inline;}
@media (prefers-color-scheme: light){
  :root:not([data-theme="dark"]) .theme-toggle .to-dark{display:inline;}
  :root:not([data-theme="dark"]) .theme-toggle .to-light{display:none;}
}
:root[data-theme="light"] .theme-toggle .to-dark{display:inline;}
:root[data-theme="light"] .theme-toggle .to-light{display:none;}

/* ---------------------------------------------------------------- step rail */
.steps{
  display:flex; align-items:center; gap:var(--space-sm);
  font-family:var(--font-mono); font-size:var(--fs-xs); line-height:var(--lh-xs);
  letter-spacing:.06em; text-transform:uppercase; color:var(--muted);
  margin-bottom:var(--space-xl);
}
.steps span{display:flex; align-items:center; gap:var(--space-s);}
.steps b{
  width:1.25rem; height:1.25rem; border-radius:50%;
  border:1px solid var(--line-strong);
  display:grid; place-items:center; font-weight:500;
}
.steps .on{color:var(--ink);}
.steps .on b{background:var(--accent); border-color:var(--accent); color:var(--accent-ink);}
.steps .rule{flex:1; height:1px; background:var(--line);}

/* ---------------------------------------------------------------- type */
h1{
  font-size:var(--fs-3xl); line-height:var(--lh-3xl); letter-spacing:var(--tr-3xl);
  font-weight:700; text-wrap:balance; margin-bottom:var(--space-m);
}
.lede{color:var(--muted); font-size:var(--fs-base); line-height:var(--lh-base);}
.eyebrow{
  font-family:var(--font-mono); font-size:var(--fs-xs); line-height:var(--lh-xs);
  letter-spacing:.12em; text-transform:uppercase; color:var(--accent);
  margin-bottom:var(--space-sm);
}

/* ---------------------------------------------------------------- panel */
.panel{
  background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius); padding:var(--space-xl);
  margin-top:var(--space-xl);
  animation:rise var(--dur-enter) var(--ease-out) both;
}
/* The one signature move in the app: panels arrive from --dist. Nothing else animates. */
@keyframes rise{ from{opacity:0; transform:translateY(var(--dist));} to{opacity:1; transform:none;} }

/* ---------------------------------------------------------------- fields */
.field{margin-bottom:var(--space-l);}
/* :last-child, NOT :last-of-type. `:last-of-type` matches per element type, so the moment a
   .field was a <fieldset> rather than a <div> it became "the last fieldset" and silently lost
   its bottom margin while the divs above kept theirs. */
.field:last-child{margin-bottom:0;}
.field label{
  display:block; margin-bottom:var(--space-sm);
  font-size:var(--fs-sm); line-height:var(--lh-sm); font-weight:500;
}
.field .hint{
  display:block; margin-top:var(--space-s);
  color:var(--muted); font-size:var(--fs-xs); line-height:var(--lh-xs);
}
textarea{
  width:100%; min-height:12rem; resize:vertical;
  background:var(--ground); color:var(--ink);
  border:1px solid var(--line-strong); border-radius:var(--radius);
  padding:var(--space-m);
  font-family:var(--font-display); font-size:var(--fs-base); line-height:var(--lh-base);
  transition:border-color var(--dur-state) var(--ease);
}
textarea:hover{border-color:var(--muted);}
textarea::placeholder{color:var(--muted);}

input[type=text],input[type=email],input[type=tel],input[type=date],select{
  width:100%; height:var(--field-h);
  background:var(--ground); color:var(--ink);
  border:1px solid var(--line-strong); border-radius:var(--radius);
  padding:0 var(--space-m);
  font-family:var(--font-display); font-size:var(--fs-base);
  transition:border-color var(--dur-state) var(--ease);
}
input::placeholder{color:var(--muted);}
input:hover,select:hover{border-color:var(--muted);}
select{appearance:none; cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),
                   linear-gradient(135deg,var(--muted) 50%,transparent 50%);
  background-position:calc(100% - 1.125rem) 1.25rem, calc(100% - .8125rem) 1.25rem;
  background-size:.3125rem .3125rem,.3125rem .3125rem; background-repeat:no-repeat;
}
.row{display:grid; gap:var(--space-l);}
@media (min-width:600px){ .row.two{grid-template-columns:1fr 1fr;} }
/* A row's own children carry the field margin, so the row itself had none and the next field
   sat flush against it — measured at a 0px gap where every other field had breathing room. */
.row.two{margin-bottom:var(--space-l);}
/* Day / month / year sits on one line at every width — three stacked dropdowns read as
   three unrelated questions. The month column is widest because it holds "September". */
.row.three{grid-template-columns:4.5rem 1fr 5.5rem; gap:var(--space-m);}

/* A fieldset is the correct grouping for three inputs answering one question. */
.dob{border:0; padding:0; min-width:0;}
.dob legend{
  padding:0; margin-bottom:var(--space-sm);
  font-size:var(--fs-sm); line-height:var(--lh-sm); font-weight:500;
}

/* consent — two separate decisions, never one checkbox */
.consent{
  display:flex; gap:var(--space-m); align-items:flex-start;
  padding:var(--space-m) 0; border-top:1px solid var(--line);
}
.consent input{
  width:1.125rem; height:1.125rem; margin-top:.1875rem; flex:none;
  accent-color:var(--accent); cursor:pointer;
}
.consent label{font-size:var(--fs-sm); line-height:var(--lh-sm); cursor:pointer;}
.consent .hint{display:block; color:var(--muted); font-size:var(--fs-xs); line-height:var(--lh-xs); margin-top:var(--space-xs);}

/* ---------------------------------------------------------------- buttons */
.btn{
  width:100%; height:var(--field-h);
  background:var(--accent); color:var(--accent-ink);
  border:1px solid var(--accent); border-radius:var(--radius);
  font-family:var(--font-display); font-size:var(--fs-base); font-weight:600;
  cursor:pointer; margin-top:var(--space-xl);
  transition:background var(--dur-state) var(--ease);
}
.btn:hover:not(:disabled){background:var(--accent-hover);}
.btn:disabled{opacity:.5; cursor:not-allowed;}
.btn-quiet{
  background:transparent; color:var(--ink); border-color:var(--line-strong);
}
.btn-quiet:hover:not(:disabled){background:var(--panel-2);}

.alt{
  margin-top:var(--space-xl); padding-top:var(--space-l);
  border-top:1px solid var(--line);
  font-size:var(--fs-sm); line-height:var(--lh-sm); color:var(--muted);
  text-align:center;
}

/* ---------------------------------------------------------------- messages */
.note{
  border:1px solid var(--line-strong); border-left-width:2px;
  border-radius:var(--radius);
  padding:var(--space-m) var(--space-l);
  font-size:var(--fs-sm); line-height:var(--lh-sm);
  margin-bottom:var(--space-l);
}
.note.error{border-left-color:var(--red); background:var(--red-ground);}
.note.ok{border-left-color:var(--accent); background:var(--accent-ground);}
.note.warn{border-left-color:var(--amber); background:var(--amber-ground);}
.note[hidden]{display:none;}
.note code{
  font-family:var(--font-mono); font-size:var(--fs-xs);
  word-break:break-all; display:block; margin-top:var(--space-sm);
  color:var(--accent);
}

.foot{
  margin-top:var(--space-xl);
  color:var(--muted); font-size:var(--fs-xs); line-height:var(--lh-xs);
}

/* ---------------------------------------------------------------- status list */
.facts{margin-top:var(--space-xl); border-top:1px solid var(--line);}
.facts div{
  display:flex; justify-content:space-between; align-items:baseline;
  gap:var(--space-l);
  padding:var(--space-m) 0; border-bottom:1px solid var(--line);
  font-size:var(--fs-sm); line-height:var(--lh-sm);
}
/* The label must not be squeezed by a long value, and a long value must not run into the
   label. An email is easily 30 characters and was doing exactly that on a narrow phone. */
.facts dt{color:var(--muted); flex:none;}
.facts dd{
  font-family:var(--font-mono); font-size:var(--fs-xs); text-align:right;
  min-width:0; overflow-wrap:anywhere;
}
.pill{
  display:inline-block; padding:.125rem var(--space-sm); border-radius:var(--radius);
  font-family:var(--font-mono); font-size:var(--fs-xs); line-height:1.5;
  letter-spacing:.04em; text-transform:uppercase;
  border:1px solid var(--line-strong); color:var(--muted);
}
.pill.on{border-color:var(--accent); color:var(--accent); background:var(--accent-ground);}
.pill.wait{border-color:var(--amber); color:var(--amber); background:var(--amber-ground);}
.pill.off{border-color:var(--line-strong); color:var(--muted); opacity:.7;}

select:disabled{opacity:.55; cursor:not-allowed;}
