/* ==========================================================================
   Mktforge — shell styles
   Palette and type are carried over from the portfolio site so the two
   properties read as the same hand. The frame (the nav and the management
   bar) is dark; its colours are the --frame-* tokens below, and they are the
   only ones to touch if the frame's colour changes again.
   ========================================================================== */

:root {
  /* Surfaces */
  --desk:        #E8DFC6;  /* the sign-in page's ground (see login.css)     */
  --paper:       #F6F1E6;  /* display field                                  */
  --paper-dim:   #EDE6D3;  /* hover / scrollbar track                        */
  --paper-line:  #D6CEBC;  /* hairlines and borders                          */

  /* Reading surfaces (readability pass, 2026-09-24).
     Modules sit on --ground and draw their boxes in --surface, so a box is
     separated from the page by brightness rather than by a faint border.
     Every module's --xx-surface / --xx-shadow / --xx-radius points here. */
  --ground:       #ECE7DB;  /* the display field behind the modules          */
  --surface:      #FFFFFF;  /* module boxes and cards                        */
  --surface-alt:  #F8F5EE;  /* alternate table rows                          */
  --shadow-card:  0 1px 2px rgba(32,36,43,.06), 0 8px 24px rgba(32,36,43,.06);
  --radius-card:  10px;

  /* Ink */
  --ink:         #20242B;
  --ink-soft:    #3C4149;
  --muted:       #5F5A4C;  /* 6.6:1 on white; the old #7A7565 fell under 4.5:1 on paper */

  /* Accent */
  --accent:      #2F6F4E;
  --accent-tint: #E4EEE7;

  /* Frame — the nav and the management bar.
     These are the only tokens that move when the frame's colour changes; the
     paper tokens above stay exactly as they were, so the display field and
     every module inside it are untouched. To try one of the other colours,
     change --frame and the eight values under it, and nothing else. */
  --frame:             #20242B;  /* nav + management bar                     */
  --frame-hover:       #2B303A;  /* nav button, profile button               */
  --frame-line:        #343A45;  /* the nav footer's rule                    */
  --frame-text:        #E9ECF1;  /* module labels, and their icons with them */
  --frame-text-strong: #FFFFFF;  /* hover, and the account name              */
  --frame-muted:       #8E96A3;  /* minimize chevron, profile caret          */
  --frame-active:      #2C3A34;  /* the module you are on                    */
  --frame-active-text: #A8E6C1;
  --frame-marker:      #4FA97A;  /* the 3px bar beside the active module     */

  /* Type */
  --font-body:    'IBM Plex Sans', system-ui, sans-serif;
  --font-display: 'Newsreader', Georgia, serif;
  --font-mono:    'IBM Plex Mono', 'Courier New', monospace;

  /* Frame geometry.
     The spec called for ~15% / ~5% / ~5%. Those ratios hold on a normal
     desktop but break at the extremes (15% of a 2560px monitor is a 384px
     nav; 15% of a 1024px laptop wraps the labels), so each one is expressed
     as its ratio with a floor and a ceiling. */
  --nav-w-open:  clamp(200px, 15vw, 260px);
  --nav-w-min:   64px;
  --nav-w:       var(--nav-w-open);
  --mgmt-h:      56px;

  --nav-pad-x:   14px;
  --radius:      3px;
  --ease:        180ms cubic-bezier(.4, 0, .2, 1);
}

body[data-nav="collapsed"] { --nav-w: var(--nav-w-min); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

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

html, body {
  height: 100%;
  margin: 0;
}

/* The shell is a fixed frame: the nav and the management bar stay put, and the
   display field is the only thing that scrolls. Nothing ever enforced that on
   the document itself, so a module whose content overflows its grid area can
   hand the PAGE a scrollbar — which scrolls the whole app up and exposes the
   body behind it. Clipping here keeps the frame nailed to the viewport.
   Scoped by data-nav, which only the app shell's body carries: login.html
   shares this stylesheet and still needs to scroll on a short window. */
body[data-nav] { overflow: hidden; }

body {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink);
  background: var(--frame);
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Inside the frame the accent green is too dark to make out against the frame
   colour; the marker green is the same hue with enough light in it to read. */
.nav :focus-visible,
.mgmt :focus-visible { outline-color: var(--frame-marker); }

/* ==========================================================================
   App frame
   The nav spans both rows (top of screen to bottom); the management bar
   occupies the top row to the right of it; the display field takes the rest.
   ========================================================================== */

/* Hidden until the auth check finishes, so a signed-out visitor never sees a
   flash of the app before being sent to the login page. */
body[data-auth="pending"] .app { visibility: hidden; }

.app {
  display: grid;
  grid-template-columns: var(--nav-w) 1fr;
  grid-template-rows: var(--mgmt-h) 1fr;
  height: 100dvh;
  transition: grid-template-columns var(--ease);
}

/* ==========================================================================
   Navigation bar
   ========================================================================== */

.nav {
  grid-column: 1;
  grid-row: 1 / span 2;
  display: flex;
  flex-direction: column;
  min-width: 0;
  position: relative;
  background: var(--frame);
  overflow: hidden;
}

/* The nav used to carry a hairline down its right edge, and the management bar
   one along its bottom. Against a dark frame the colour change IS the edge, and
   a line drawn on top of it reads as a seam, so both are gone. */

/* Logo block: exactly as tall as the management bar, so the wordmark sits on
   the same optical line as the profile on the other side of the screen. */
.nav__logo {
  flex: 0 0 var(--mgmt-h);
  display: flex;
  align-items: center;
  padding: 0 var(--nav-pad-x);
}

/* Logo files live in assets/img: the full lockup (squares + wordmark) and
   the squares on their own for the minimized nav. Both are SVG traced from
   mktforge-logo.png, so they stay sharp at any size. */
.logo { display: flex; align-items: center; line-height: 0; border-radius: var(--radius); }

a.logo { cursor: pointer; transition: opacity var(--ease); }
a.logo:hover { opacity: .8; }

.logo img { display: block; height: 24px; width: auto; }

/* Expanded lockup: sized so its squares match the 24px minimized mark.
   In the SVG the squares and the "M" are both 252 units tall (the wordmark
   was scaled down so its cap height lines up with the squares); the viewBox
   is 1835 x 324, the extra height being the "g" descender. So 24px squares
   = a 175 x 31px lockup. On narrow screens, where the nav is too slim for
   that, it scales down to fit instead of spilling past the nav. */
.nav__logo .logo { max-width: 100%; }
.logo .logo__full { width: calc(24px * 1835 / 252); max-width: 100%; height: auto; }

.logo .logo__mark { display: none; }

body[data-nav="collapsed"] .nav__logo { justify-content: center; padding: 0; }
body[data-nav="collapsed"] .logo .logo__full { display: none; }
body[data-nav="collapsed"] .logo .logo__mark { display: block; }

/* Module buttons start below the line where the management bar meets the nav */
.nav__list {
  flex: 1 1 auto;
  list-style: none;
  margin: 0;
  padding: 22px 8px 8px;
  overflow-y: auto;         /* room to grow when there are many modules */
  overflow-x: hidden;
}

.nav__item + .nav__item { margin-top: 4px; }

.nav__button {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--frame-text);
  font-size: 13.5px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--ease), color var(--ease);
}

.nav__button:hover { background: var(--frame-hover); color: var(--frame-text-strong); }

.nav__button[aria-current="page"] {
  background: var(--frame-active);
  color: var(--frame-active-text);
  font-weight: 600;
}

/* Active marker on the left edge of the button */
.nav__button[aria-current="page"]::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 0 2px 2px 0;
  background: var(--frame-marker);
}

.nav__icon {
  flex: 0 0 20px;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
}

.nav__icon svg { width: 20px; height: 20px; display: block; }

.nav__label {
  /* Long module names wrap to a second line rather than being cut off —
     "Battle Card Generator" doesn't fit one line at the 200–230px nav widths
     most laptops get. */
  min-width: 0;
  white-space: normal;
  line-height: 1.3;
  overflow-wrap: break-word;
}

/* Collapsed: icon only, with a tooltip on hover */
body[data-nav="collapsed"] .nav__list { padding-left: 6px; padding-right: 6px; }
body[data-nav="collapsed"] .nav__button { justify-content: center; padding: 10px 0; }
body[data-nav="collapsed"] .nav__label { display: none; }

body[data-nav="collapsed"] .nav__button::after {
  content: attr(data-label);
  position: absolute;
  left: calc(100% + 10px);
  top: 50%;
  transform: translateY(-50%);
  padding: 5px 9px;
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease;
  z-index: 40;
}

body[data-nav="collapsed"] .nav__button:hover::after,
body[data-nav="collapsed"] .nav__button:focus-visible::after { opacity: 1; }

/* Minimize control, bottom-right of the nav */
.nav__footer {
  flex: 0 0 auto;
  display: flex;
  justify-content: flex-end;
  padding: 10px var(--nav-pad-x) 14px;
  border-top: 1px solid var(--frame-line);
}

body[data-nav="collapsed"] .nav__footer { justify-content: center; padding-left: 0; padding-right: 0; }

.nav__minimize {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--frame-muted);
  cursor: pointer;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}

.nav__minimize:hover {
  background: var(--frame-hover);
  border-color: var(--frame-line);
  color: var(--frame-text-strong);
}

.nav__minimize-icon {
  width: 9px;
  height: 9px;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(1px, -1px);
  transition: transform var(--ease);
}

body[data-nav="collapsed"] .nav__minimize-icon {
  transform: rotate(-135deg) translate(1px, -1px);
}

/* ==========================================================================
   Management bar
   ========================================================================== */

.mgmt {
  grid-column: 2;
  grid-row: 1;
  position: relative;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 16px 0 20px;
  background: var(--frame);
}

.mgmt__spacer { flex: 1 1 auto; }

.profile { position: relative; }

.profile__button {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  cursor: pointer;
  transition: background var(--ease), border-color var(--ease);
}

.profile__button:hover { background: var(--frame-hover); border-color: var(--frame-line); }

.profile__avatar {
  flex: 0 0 30px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: var(--frame-hover);
  border: 1px solid var(--frame-line);
  color: var(--frame-muted);
}

.profile__avatar svg { width: 30px; height: 30px; display: block; }
.profile__avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The name is never truncated — a long name pushes everything else left,
   which is the behaviour the spec asks for. */
.profile__name {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--frame-text-strong);
  white-space: nowrap;
}

.profile__caret {
  width: 0;
  height: 0;
  border-left: 4.5px solid transparent;
  border-right: 4.5px solid transparent;
  border-top: 5px solid var(--frame-muted);
  transition: transform var(--ease);
}

.profile__button[aria-expanded="true"] .profile__caret { transform: rotate(180deg); }

/* Dropdown */
.menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 170px;
  padding: 5px;
  background: var(--paper);
  border: 1px solid var(--paper-line);
  border-radius: var(--radius);
  box-shadow: 0 10px 26px rgba(32, 36, 43, .14);
  z-index: 50;
}

.menu[hidden] { display: none; }

.menu__item {
  display: block;
  width: 100%;
  padding: 9px 11px;
  border: 0;
  border-radius: 2px;
  background: transparent;
  color: var(--ink-soft);
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}

.menu__item:hover { background: var(--paper-dim); color: var(--ink); }

/* Company dropdown — left of the account menu, with a thin rule between */
.mgmt__divider {
  flex: 0 0 1px;
  width: 1px;
  height: 26px;
  background: #5B626E;
  margin: 0 -8px;              /* sits in the middle of the 18px gap */
}

.company { position: relative; }

.company__button {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  cursor: pointer;
  transition: background var(--ease), border-color var(--ease);
}
.company__button:hover { background: var(--frame-hover); border-color: var(--frame-line); }
.company__button[aria-expanded="true"] .profile__caret { transform: rotate(180deg); }

.company__name {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--frame-text-strong);
  white-space: nowrap;
}

.company__menu { min-width: 240px; max-height: 70vh; overflow-y: auto; }

.company__item { position: relative; padding-left: 26px; white-space: nowrap; }
.company__item[aria-checked="true"] { color: var(--ink); font-weight: 600; }
.company__item[aria-checked="true"]::before {
  content: '';
  position: absolute;
  left: 11px;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--accent);
}

.company__rule { height: 1px; margin: 5px 4px; background: var(--paper-line); }

.company__add { display: flex; align-items: center; gap: 8px; padding-left: 11px; }
.company__plus { color: var(--accent); font-size: 17px; font-weight: 600; line-height: 1; width: 8px; text-align: center; }
.company__add.is-full { color: #A8371F; cursor: default; }
.company__add.is-full:hover { background: transparent; color: #A8371F; }

body[data-switching="true"] { cursor: progress; }

/* ==========================================================================
   Modal (Mktforge.confirm)
   ========================================================================== */

.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(32, 36, 43, .45);
}

.modal__card {
  width: min(460px, 100%);
  padding: 26px 26px 22px;
  background: var(--paper);
  border: 1px solid var(--paper-line);
  border-radius: var(--radius);
  box-shadow: 0 18px 44px rgba(32, 36, 43, .28);
}

.modal__message { margin: 0 0 22px; color: var(--ink); font-size: 15px; line-height: 1.55; }

.modal__actions { display: flex; justify-content: center; gap: 12px; }

.modal__btn {
  padding: 9px 18px;
  border: 1px solid var(--paper-line);
  border-radius: var(--radius);
  background: #FFFDF7;
  color: var(--ink-soft);
  font: 500 13.5px var(--font-body);
  cursor: pointer;
}
.modal__btn:hover { background: var(--paper-dim); color: var(--ink); }
.modal__btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.modal__btn--primary:hover { background: #285F43; color: #fff; }
.modal__btn--danger { background: #A8371F; border-color: #A8371F; color: #fff; }
.modal__btn--danger:hover { background: #8F2E19; color: #fff; }

/* ==========================================================================
   Display field — the only scrolling region
   ========================================================================== */

.display {
  grid-column: 2;
  grid-row: 2;
  /* Containing block for anything a module positions absolutely. Without this
     such an element resolves against the initial containing block instead, so
     it lands at a document coordinate rather than inside this scroller and
     stretches the PAGE's scroll height — the app then scrolls as a whole and
     exposes the body behind it. Find My Customer's .fmc__sr hit exactly that. */
  position: relative;
  min-width: 0;
  overflow-y: scroll;   /* always reserve the track so content never shifts */
  overflow-x: hidden;
  background: var(--ground);
  scrollbar-color: var(--paper-line) var(--paper-dim);
  scrollbar-width: thin;
}

.display:focus { outline: none; }

.display::-webkit-scrollbar { width: 12px; }
.display::-webkit-scrollbar-track { background: var(--paper-dim); }
.display::-webkit-scrollbar-thumb {
  background: var(--paper-line);
  border: 3px solid var(--paper-dim);
  border-radius: 999px;
}
.display::-webkit-scrollbar-thumb:hover { background: var(--muted); }

.display__mount { min-height: 100%; }

/* ==========================================================================
   Crude small-screen fallback.
   Desktop is the target for now; this only keeps things usable rather than
   being a designed mobile layout.
   ========================================================================== */

@media (max-width: 860px) {
  :root { --nav-w-open: var(--nav-w-min); }
  body[data-nav="expanded"] .nav__label,
  body[data-nav="expanded"] .logo .logo__full { display: none; }
  body[data-nav="expanded"] .logo .logo__mark { display: block; }
  body[data-nav="expanded"] .nav__logo { justify-content: center; padding: 0; }
  body[data-nav="expanded"] .nav__button { justify-content: center; padding: 10px 0; }
  .nav__minimize { display: none; }
}

/* ==========================================================================
   Notices (mktforge:notify)
   ========================================================================== */

.toasts {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none;
}

.toast {
  max-width: 360px;
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--ink);
  color: #F6F1E6;
  font-size: 13px;
  line-height: 1.45;
  box-shadow: 0 6px 20px rgba(32, 36, 43, .18);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--ease), transform var(--ease);
}

.toast.is-in { opacity: 1; transform: none; }
.toast--error { background: #A8371F; }

/* ==========================================================================
   Picker (MktforgeKit.attachPicker) — My Company values under a text field
   ========================================================================== */

.mf-picker-host { position: relative; }

.mf-picker {
  position: absolute;
  z-index: 20;
  max-height: 240px;
  overflow-y: auto;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: #FFFDF7;
  border: 1px solid var(--paper-line);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(32, 36, 43, .12);
  text-align: left;
}

.mf-picker[hidden] { display: none; }

.mf-picker__option {
  padding: 7px 10px;
  border-radius: 4px;
  font-size: 14px;
  line-height: 1.35;
  color: var(--ink);
  cursor: pointer;
  overflow-wrap: anywhere;
}

.mf-picker__option:hover,
.mf-picker__option.is-active { background: var(--accent-tint); }

/* ==========================================================================
   Background-run lights (Mktforge.reportActivity)
   ========================================================================== */

.nav__status {
  flex: none;
  display: none;
  width: 9px;
  height: 9px;
  margin-left: auto;
  border-radius: 50%;
}

.nav__status[data-state="running"] {
  display: block;
  background: #FFC24D;
  box-shadow: 0 0 0 2px rgba(255, 194, 77, .3);
  animation: nav-status-pulse 1.8s ease-in-out infinite;
}

.nav__status[data-state="error"] {
  display: block;
  background: #FF6F52;
  box-shadow: 0 0 0 2px rgba(255, 111, 82, .3);
}

.nav__status[data-state="done"] {
  display: block;
  background: #4FD98A;
  box-shadow: 0 0 0 2px rgba(79, 217, 138, .3);
}

@keyframes nav-status-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .55; }
}

/* screen-reader only */
.nav__status-text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Icon-only nav: the dot sits on the icon's top-right corner. Its ring picks
   up whatever the button sits on, including the active module's tint — the
   light now shows on the module you're looking at too. */
body[data-nav="collapsed"] .nav__status {
  position: absolute;
  top: 6px;
  right: calc(50% - 16px);
  margin: 0;
  border: 2px solid var(--frame);
  width: 11px;
  height: 11px;
}

body[data-nav="collapsed"] .nav__button[aria-current="page"] .nav__status {
  border-color: var(--frame-active);
}

@media (max-width: 860px) {
  body[data-nav="expanded"] .nav__status {
    position: absolute;
    top: 6px;
    right: calc(50% - 16px);
    margin: 0;
    border: 2px solid var(--frame);
    width: 11px;
    height: 11px;
  }

  body[data-nav="expanded"] .nav__button[aria-current="page"] .nav__status {
    border-color: var(--frame-active);
  }
}

/* ==========================================================================
   Readability: striped rows in the research boxes' tables.
   :where() keeps this at zero specificity, so any module rule that colours a
   row or cell still wins. Market Tracker is left out on purpose — its row
   colours carry meaning (sentiment), and stripes would muddy them.
   ========================================================================== */

.display :where(.pb__box, .fmc__box, .mo__box, .bcg__box) :where(tbody tr:nth-child(even)) > td {
  background: var(--surface-alt);
}

/* ==========================================================================
   API key badge (MktforgeKit.byok) — inside a tool module's title, to the
   right of the name. Its own font, so it doesn't inherit the display serif.
   ========================================================================== */

.mf-byok {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: 16px;
  padding: 4px 12px 4px 10px;
  border-radius: 999px;
  vertical-align: middle;
  position: relative;
  top: -3px;
  font: 500 13.5px/1.4 var(--font-body);
  letter-spacing: 0;
  white-space: nowrap;
  color: var(--accent);
  background: var(--accent-tint);
  border: 1px solid rgba(47, 111, 78, .25);
}

.mf-byok[hidden] { display: none; }

.mf-byok__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}

.mf-byok.is-warn {
  color: #8A5A00;
  background: #FBF1DC;
  border-color: rgba(138, 90, 0, .3);
  white-space: normal;
}
