/* KitchenDrop brand foundation — tokens, type, and primitives.
   Loaded by every page before its own stylesheet. */

/* ---------- Colour ----------
   Taken from the flame mark: ember orange is the brand, deep navy is the ink
   and the counterweight, on warm paper rather than a cool grey. The two logo
   colours do different jobs — orange carries action and emphasis, navy carries
   text, surfaces and anything that must not compete with a button. */

:root,
[data-theme="light"] {
  --brand: #dd5a1f;
  --brand-strong: #b8431a;
  --brand-wash: #fdeee4;

  /* The mark's second colour. Used where a badge or meter has to read as
     distinct from the brand orange instead of blending into it. */
  --navy: #2c3b69;
  --navy-strong: #1b2444;
  --navy-wash: #eaeef7;

  --gold: #8a6510;
  --gold-wash: #f7efd6;

  --violet: #5b3fa8;
  --violet-wash: #ece6f8;
  --shot-clip: #2c3b69;
  --shot-photo: #8a6510;
  --shot-lib: #2e7d5b;
  --shot-gen: #5b3fa8;

  /* One colour per specialist agent, taken from the palette above rather than
     invented, so a pitch pill, a mix meter and a format card all agree on what
     Reach looks like. They were four hardcoded hexes repeated in three places,
     and the two blues went unreadable the moment the theme flipped.
     These resolve against whichever --navy/--good/--violet wins on :root, so
     one declaration covers both themes. */
  --intent-reach: var(--navy);
  --intent-reach-wash: var(--navy-wash);
  --intent-craving: var(--brand-strong);
  --intent-craving-wash: var(--brand-wash);
  --intent-trust: var(--good);
  --intent-trust-wash: var(--good-wash);
  --intent-booking_order: var(--violet);
  --intent-booking_order-wash: var(--violet-wash);

  --bg: #f9f7f4;
  --surface: #ffffff;
  --surface-2: #f3f0eb;
  --surface-3: #e8e3da;
  --field: #ffffff;

  --fg: #16203a;
  --fg-2: #4a5468;
  --fg-3: #78808f;
  --fg-4: #a6adb8;

  --line: #e4dfd6;
  --line-soft: #f0ece5;
  --line-strong: #d0c8bc;

  --good: #2e7d5b;
  --good-wash: #e8f4ee;
  --warn: #a86a12;
  --warn-wash: #fbf1de;
  --bad: #b23b2c;
  --bad-wash: #fbecea;

  --scrim: rgba(16, 24, 40, 0.55);
  --veil: rgba(249, 247, 244, 0.85);

  /* A card is told apart from the page by its border and its surface, not by
     how far it floats. Depth is spent on the things that genuinely sit over
     the page -- a menu, a sheet, a dialog -- and everything resting in the
     flow gets a hairline and almost nothing else. */
  --shadow-1: 0 1px 2px rgba(22, 32, 58, 0.04);
  --shadow-2: 0 1px 2px rgba(22, 32, 58, 0.04), 0 6px 16px -10px rgba(22, 32, 58, 0.1);
  --shadow-3: 0 2px 6px rgba(22, 32, 58, 0.05), 0 20px 40px -16px rgba(22, 32, 58, 0.18);

  /* Runs the mark's own ramp — amber into ember — but ends deep enough that
     white button text still clears the 3:1 contrast floor for UI text. */
  --grad-brand: linear-gradient(135deg, #f0862c 0%, #e05f21 55%, #c4481b 100%);
  --grad-brand-hover: linear-gradient(135deg, #f79433 0%, #ea6b27 55%, #d65220 100%);
  --grad-navy: linear-gradient(135deg, #3a4a7d 0%, #2c3b69 55%, #1b2444 100%);
  --grad-good: linear-gradient(135deg, #2f8f6d 0%, #1f6b50 100%);
  --grad-violet: linear-gradient(135deg, #7c5cd6 0%, #5b3fa8 100%);
  --grad-danger: linear-gradient(180deg, #d6503d 0%, #b23b2c 100%);
  --grad-danger-hover: linear-gradient(180deg, #e05a47 0%, #c04434 100%);
}

[data-theme="dark"] {
  --brand: #f5883a;
  --brand-strong: #fba355;
  --brand-wash: rgba(245, 136, 58, 0.16);

  --navy: #8b99cd;
  --navy-strong: #a3aeda;
  --navy-wash: rgba(139, 153, 205, 0.16);

  --gold: #ddb65a;
  --gold-wash: rgba(221, 182, 90, 0.14);

  --violet: #b09ae8;
  --violet-wash: #2b2340;
  --shot-clip: #8b99cd;
  --shot-photo: #ddb65a;
  --shot-lib: #55b98e;
  --shot-gen: #b09ae8;

  --bg: #12151f;
  --surface: #191d2a;
  --surface-2: #212635;
  --surface-3: #2d3346;
  --field: #141824;

  --fg: #edeff4;
  --fg-2: #a8afc0;
  --fg-3: #7e8698;
  --fg-4: #5c6478;

  --line: #2d3346;
  --line-soft: #212635;
  --line-strong: #3e4560;

  --good: #55b98e;
  --good-wash: rgba(85, 185, 142, 0.14);
  --warn: #d3993f;
  --warn-wash: rgba(211, 153, 63, 0.14);
  --bad: #e0705f;
  --bad-wash: rgba(224, 112, 95, 0.14);

  --scrim: rgba(0, 0, 0, 0.7);
  --veil: rgba(18, 21, 31, 0.85);

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-2: 0 1px 2px rgba(0, 0, 0, 0.25), 0 6px 16px -10px rgba(0, 0, 0, 0.5);
  --shadow-3: 0 2px 6px rgba(0, 0, 0, 0.3), 0 20px 40px -16px rgba(0, 0, 0, 0.65);

  --grad-brand: linear-gradient(135deg, #f79a45 0%, #ee7430 55%, #e05f24 100%);
  --grad-brand-hover: linear-gradient(135deg, #fca752 0%, #f5823a 55%, #ea6c2b 100%);
  --grad-navy: linear-gradient(135deg, #4a5a92 0%, #3a4a7d 55%, #2c3b69 100%);
  --grad-good: linear-gradient(135deg, #3aa47f 0%, #27805f 100%);
  --grad-violet: linear-gradient(135deg, #8f70e4 0%, #6b4dbd 100%);
  --grad-danger: linear-gradient(180deg, #e0705f 0%, #c65545 100%);
  --grad-danger-hover: linear-gradient(180deg, #e88070 0%, #d06050 100%);
}

/* ---------- Type & metrics ---------- */

:root {
  --display: "Fraunces", "Iowan Old Style", Georgia, serif;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Aliases for names used around the app that predate the numbered scale.
     Written as var() so each still resolves per-theme at the point of use. */
  --fg-1: var(--fg);
  --surface-1: var(--surface);
  --shadow-sm: var(--shadow-1);
  --shadow-md: var(--shadow-2);

  /* Softer than a web app's usual 4/8/12. The corner is the loudest thing a
     flat interface says about itself, and at 8px a button reads as a form
     control on a page; at 10-14 it reads as a surface you can press. Every
     primitive here -- button, field, card, pill -- takes its corner from this
     scale, so the whole portal moves together rather than one screen at a
     time. Literal radii elsewhere (a 4px thumbnail, a 6px icon button) are
     deliberately below the scale and stay where they are. */
  --r-xs: 6px;
  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 28px;
  --r-pill: 999px;

  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}

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

/* A class that sets `display` otherwise beats the attribute, leaving elements
   marked hidden still painted — spinners being the obvious casualty. */
[hidden] {
  display: none !important;
}

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

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  /* Inter sets a touch wide at UI sizes. The headings already pull in; the
     body reading loose against them was the tell. */
  letter-spacing: -0.01em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

h1,
h2,
h3 {
  font-family: var(--display);
  font-weight: 600;
  font-variation-settings: "SOFT" 4, "WONK" 0;
  letter-spacing: -0.012em;
  line-height: 1.12;
}

h4,
h5,
h6 {
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.3;
}

a {
  color: inherit;
}

img,
svg,
video {
  display: block;
  max-width: 100%;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

::selection {
  background: var(--brand);
  color: #fff;
}

:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Small-caps label used above section headings and over form groups. */
.eyebrow {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--fg-3);
}

/* ---------- Logo lockup ---------- */

.kd-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  text-decoration: none;
  color: var(--fg);
}

/* The flame is a tall, narrow silhouette (roughly 4:5), so a square box paints
   it far narrower than the box implies — at 1.45em it inked only ~18px wide
   beside a ~104px wordmark and read as an afterthought. Sized off the mark's
   height instead, with width left to the aspect ratio so no side padding is
   reintroduced. */
.kd-logo img {
  height: 2em;
  width: auto;
  flex: none;
}

.kd-logo b {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.06em;
  letter-spacing: -0.025em;
  white-space: nowrap;
}

/* ---------- Buttons ---------- */

.btn {
  --btn-bg: var(--surface);
  --btn-fg: var(--fg);
  --btn-line: var(--line-strong);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0.62em 1.05em;
  border: 1px solid var(--btn-line);
  border-radius: var(--r-sm);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  /* A label that breaks mid-button reads as a rendering fault. Nowrap also
     puts a floor under the button's min-content width, so a flex row shrinks
     the prose beside it rather than squeezing the action. */
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s var(--ease), border-color 0.15s var(--ease),
    transform 0.08s var(--ease), color 0.15s var(--ease);
}

.btn:hover {
  background: var(--surface-2);
}

.btn:active {
  transform: translateY(1px);
}

/* Disabled has to read as unavailable at a glance. Fading a gradient to 55%
   leaves a button that still looks painted and pressable — people click it and
   then wonder why nothing happened — so the treatment strips the paint instead
   of thinning it: flat light surface, muted label, no shadow, no hover, no
   press. Applies to every button in the app, not one form's save. */
.btn:disabled,
.btn[disabled],
.btn[aria-disabled="true"] {
  background: var(--surface-2);
  background-image: none;
  border-color: var(--line);
  color: var(--fg-4);
  box-shadow: none;
  text-shadow: none;
  opacity: 1;
  cursor: not-allowed;
  transform: none;
}

.btn:disabled:hover,
.btn[disabled]:hover,
.btn[aria-disabled="true"]:hover {
  background: var(--surface-2);
  border-color: var(--line);
}

.btn svg {
  flex: none;
}

/* The ramp stays -- it is the mark's own amber-into-ember and it is what makes
   the button read as ours rather than as a default blue. What went is the
   moulding around it: a highlight inset along the top edge, a shadow inset
   along the bottom and a drop shadow under the label, which together drew a
   physical button with a bevel. Nothing else in the portal is lit from above,
   so the one element pretending to be was the one that looked its age. Flat
   paint, one soft brand-tinted shadow to lift it off the page, and the press
   is a press rather than a dent. */
.btn-primary {
  --btn-fg: #fff;
  --btn-line: transparent;
  background: var(--grad-brand);
  box-shadow: 0 1px 2px rgba(140, 55, 20, 0.16), 0 4px 12px -6px rgba(196, 72, 27, 0.32);
}

.btn-primary:hover {
  background: var(--grad-brand-hover);
  border-color: transparent;
  box-shadow: 0 1px 2px rgba(140, 55, 20, 0.18), 0 6px 16px -6px rgba(196, 72, 27, 0.38);
}

.btn-primary:active {
  background: var(--grad-brand);
  box-shadow: 0 1px 2px rgba(140, 55, 20, 0.16);
}

/* Dark mode brightens the ember, so the button flips to ink-on-orange. */
[data-theme="dark"] .btn-primary {
  --btn-fg: #101828;
  --btn-line: transparent;
}

[data-theme="dark"] ::selection {
  color: #101828;
}



.btn-quiet {
  --btn-line: transparent;
  --btn-bg: transparent;
  color: var(--fg-2);
}

.btn-quiet:hover {
  background: var(--surface-2);
  color: var(--fg);
}

.btn-lg {
  padding: 0.85em 1.4em;
  font-size: 0.98rem;
}

.btn-block {
  width: 100%;
}

/* ---------- Form controls ---------- */

.field {
  margin-bottom: 1.1rem;
}

.field label,
.field-label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--fg-2);
  margin-bottom: 0.35rem;
}

.field .hint {
  display: block;
  font-size: 0.78rem;
  color: var(--fg-3);
  margin-top: 0.4rem;
  line-height: 1.45;
}

.input {
  width: 100%;
  padding: 0.62em 0.75em;
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: 0.94rem;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.input::placeholder {
  color: var(--fg-4);
}

.input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-wash);
}

/* A locked field that still looks writable gets typed into. Same reasoning as
   the disabled button above: strip the paint rather than thin it. */
.input:disabled {
  background: var(--surface-2);
  color: var(--fg-4);
  cursor: not-allowed;
}

select.input {
  appearance: none;
  cursor: pointer;
  padding-right: 2.1em;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2376837a' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7em center;
  background-size: 15px;
}

textarea.input {
  resize: vertical;
  min-height: 4.5em;
  line-height: 1.5;
}

/* ---------- Toggle ---------- */

.toggle {
  position: relative;
  flex: none;
  width: 40px;
  height: 23px;
}

.toggle input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}

.toggle span {
  position: absolute;
  inset: 0;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  border: 1px solid var(--line);
  transition: background-color 0.18s var(--ease), border-color 0.18s var(--ease);
  pointer-events: none;
}

.toggle span::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-1);
  transition: transform 0.18s var(--ease);
}

.toggle input:checked + span {
  background: var(--brand);
  border-color: var(--brand);
}

.toggle input:checked + span::after {
  transform: translateX(17px);
}

.toggle input:focus-visible + span {
  box-shadow: 0 0 0 3px var(--brand-wash);
}

/* ---------- Status pill ---------- */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.2em 0.55em;
  border-radius: var(--r-xs);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--fg-2);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.pill-good {
  background: var(--good-wash);
  border-color: transparent;
  color: var(--good);
}

.pill-warn {
  background: var(--warn-wash);
  border-color: transparent;
  color: var(--warn);
}

.pill-bad {
  background: var(--bad-wash);
  border-color: transparent;
  color: var(--bad);
}

.pill-brand {
  background: var(--brand-wash);
  border-color: transparent;
  color: var(--brand);
}

.pill-gold {
  background: var(--gold-wash);
  border-color: transparent;
  color: var(--gold);
}

/* A slow pulse for anything the worker is still chewing on. */
.pill-live::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  animation: kd-pulse 1.6s var(--ease) infinite;
}

@keyframes kd-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

/* ---------- Theme switch ---------- */

.theme-btn {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--fg-2);
  cursor: pointer;
  transition: background-color 0.15s var(--ease), color 0.15s var(--ease);
}

.theme-btn:hover {
  background: var(--surface-2);
  color: var(--fg);
}

.theme-btn svg {
  width: 16px;
  height: 16px;
}

/* ---------- Toasts (replaces alert()) ---------- */

.toast-stack {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 300;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(420px, calc(100vw - 32px));
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: 0.65em;
  padding: 0.75em 0.9em;
  border-radius: var(--r-md);
  background: var(--fg);
  color: var(--bg);
  font-size: 0.87rem;
  line-height: 1.4;
  box-shadow: var(--shadow-3);
  animation: kd-toast-in 0.24s var(--ease);
}

.toast.leaving {
  animation: kd-toast-out 0.18s var(--ease) forwards;
}

.toast svg {
  width: 16px;
  height: 16px;
  margin-top: 2px;
  flex: none;
}


@keyframes kd-toast-in {
  from { opacity: 0; transform: translateY(10px) scale(0.98); }
  to { opacity: 1; transform: none; }
}

@keyframes kd-toast-out {
  to { opacity: 0; transform: translateY(6px); }
}

/* ---------- Dialog ---------- */

.sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: var(--scrim);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

.sheet-backdrop.open {
  display: flex;
  animation: kd-fade 0.16s var(--ease);
}

body.sheet-open {
  overflow: hidden;
}

.sheet {
  width: 100%;
  max-width: 430px;
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  padding: 1.4rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
  animation: kd-sheet-in 0.22s var(--ease);
}

.sheet-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.2rem;
}

.sheet-head h3 {
  font-size: 1.25rem;
}

.sheet-head p {
  font-size: 0.85rem;
  color: var(--fg-3);
  margin-top: 0.2rem;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border: none;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--fg-3);
  cursor: pointer;
  transition: background-color 0.15s var(--ease), color 0.15s var(--ease);
}

.icon-btn:hover {
  background: var(--surface-2);
  color: var(--fg);
}

@keyframes kd-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes kd-sheet-in {
  from { opacity: 0; transform: translateY(12px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

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