/* Gift Tool — ivory ground, deep ink, one brass accent.
   Every colour is a custom property; the dark block redefines the same names. */

:root {
  --bg: #FBFAF6;
  --card: #FFFFFF;
  --ink: #1C1A16;
  --mute: #6E685B;
  --faint: #9A9385;
  --rule: #E7E2D6;
  --accent: #8A6B2C;
  --accent-ink: #FFFFFF;
  --accent-soft: #F4EEE1;
  --good: #3F6B4A;
  --bad: #9A3B2C;
  --shadow: 0 1px 2px rgba(28, 26, 22, .05), 0 8px 24px rgba(28, 26, 22, .05);
  --scrim: rgba(28, 26, 22, .32);
  --radius: 12px;
  /* Caret for combobox inputs. The colour has to be baked into the data: URI —
     a var() can't be interpolated inside one — so it lives here as a token
     rather than as a literal down in the rules, and the dark block restates it.
     %23 is a URL-encoded '#'. Matches --mute. */
  --caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236E685B' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #15140F;
    --card: #1E1C17;
    --ink: #F2EFE6;
    --mute: #9A9385;
    --faint: #6E685B;
    --rule: #302D25;
    --accent: #D6AC5E;
    --accent-ink: #1C1A16;
    --accent-soft: #2A2519;
    --good: #7FB08C;
    --bad: #E0836F;
    --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px rgba(0, 0, 0, .25);
    --scrim: rgba(0, 0, 0, .55);
    --caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%239A9385' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 680px; margin: 0 auto; padding: 40px 20px 96px; }

h1 { font-size: 26px; letter-spacing: -.02em; margin: 0; }
h2 { font-size: 19px; letter-spacing: -.01em; margin: 0; }
h3 { font-size: 15px; margin: 0; }
p  { margin: 0 0 12px; }

a { color: var(--accent); }

.masthead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; margin-bottom: 6px;
}
.tagline { color: var(--mute); font-size: 14px; margin-bottom: 28px; }

/* ------------------------------------------------------------------ atoms */

.card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px 20px;
  margin-bottom: 14px;
}

label { display: block; font-size: 13px; font-weight: 600; color: var(--mute); margin: 0 0 5px; }

input, textarea, select {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 9px 11px;
}
input:focus, textarea:focus, select:focus {
  outline: 2px solid var(--accent); outline-offset: 1px; border-color: transparent;
}
textarea { resize: vertical; min-height: 84px; }

/* A list-backed input is a combobox: pick a suggestion or type your own. Safari
   and Chrome disagree about whether to draw an affordance, and without one it
   reads as a plain text box, so draw our own. The list itself is native browser
   UI and can't be styled. */
input[list] {
  background-image: var(--caret);
  background-repeat: no-repeat;
  background-position: right 11px center;
  padding-right: 30px;
}
/* Chrome adds its own picker button on top of ours; hide it. */
input[list]::-webkit-calendar-picker-indicator { opacity: 0; }

/* A currency field. The $ sits inside the input because that is where the eye
   is at the moment of typing — a "(USD)" in the label is read once and forgotten.
   pointer-events: none is load-bearing: without it the symbol swallows the click
   that should focus the field. */
.money { position: relative; }
.money > .unit {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  color: var(--mute); pointer-events: none;
}
.money input { padding-left: 24px; }

/* The gift-days picker on the add form. */
.occ-picker { display: flex; flex-direction: column; gap: 9px; }
.occ-pick { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.occ-pick > label {
  display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: 14px; font-weight: 500; color: var(--ink); min-width: 148px;
}
.occ-pick input[type="checkbox"] { width: auto; margin: 0; accent-color: var(--accent); }
/* Hidden until the day is ticked — an unchecked row has nothing to say. */
.occ-inputs { display: none; gap: 6px; flex: 1; min-width: 0; }
.occ-pick.on .occ-inputs { display: flex; }
.occ-inputs select, .occ-inputs input {
  width: auto; flex: 1; min-width: 0; padding: 6px 8px; font-size: 14px;
}
/* The amount lives on the same row as the day, and appears with it: an
   unticked date has nothing to spend. Fixed width so the column of $ fields
   lines up down the picker regardless of how wide each date control is. */
.occ-money { position: relative; display: none; width: 104px; flex: none; }
.occ-pick.on .occ-money { display: block; }
.occ-money > .unit {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  color: var(--mute); pointer-events: none; font-size: 14px;
}
.occ-money input {
  width: 100%; padding: 6px 8px 6px 21px; font-size: 14px;
}
/* Dates and amount stack under the label on a narrow screen rather than
   squeezing into an unreadable row. */
@media (max-width: 560px) {
  .occ-money { width: 100%; }
}

.field { margin-bottom: 14px; }
.row { display: flex; gap: 12px; }
.row > * { flex: 1; min-width: 0; }

button {
  font: inherit; font-weight: 600; cursor: pointer;
  border-radius: 8px; border: 1px solid var(--rule);
  background: var(--card); color: var(--ink);
  padding: 9px 15px;
}
button:hover { border-color: var(--accent); }
button.go { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
button.go:hover { filter: brightness(1.08); }
button.quiet { border-color: transparent; background: transparent; color: var(--mute); padding: 6px 8px; }
button.quiet:hover { color: var(--accent); border-color: transparent; }
button.danger:hover { border-color: var(--bad); color: var(--bad); }
button[disabled] { opacity: .5; cursor: default; }

.linkbtn {
  background: none; border: none; padding: 0; font: inherit;
  color: var(--accent); text-decoration: underline; cursor: pointer;
}

.note {
  border: 1px solid var(--rule); background: var(--accent-soft);
  border-radius: 8px; padding: 10px 13px; font-size: 14px; margin-bottom: 14px;
}
.note.err { border-color: var(--bad); color: var(--bad); background: transparent; }
.note.ok  { border-color: var(--good); color: var(--good); background: transparent; }

.pill {
  display: inline-block; font-size: 12px; font-weight: 600;
  padding: 2px 9px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); border: 1px solid var(--rule);
}
.muted { color: var(--mute); }
.faint { color: var(--faint); }
.small { font-size: 13px; }
.stack { display: flex; flex-direction: column; gap: 4px; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.divider { height: 1px; background: var(--rule); margin: 16px 0; border: 0; }

/* ------------------------------------------------------------------ tabs */

.tabs { display: flex; gap: 4px; margin-bottom: 18px; border-bottom: 1px solid var(--rule); }
.tabs button {
  border: none; background: none; border-radius: 0; color: var(--mute);
  padding: 8px 12px; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tabs button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); }

/* --------------------------------------------------------------- roster */

.recipient-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.meter { height: 6px; border-radius: 999px; background: var(--rule); overflow: hidden; margin: 10px 0 6px; }
.meter > span { display: block; height: 100%; background: var(--accent); }
.meter.over > span { background: var(--bad); }

.occasion-list { list-style: none; margin: 12px 0 0; padding: 0; }
.occasion-list li {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 7px 0; border-top: 1px solid var(--rule); font-size: 14px;
}

/* ----------------------------------------------------------------- menu */

.idea { border-top: 1px solid var(--rule); padding: 16px 0; }
.idea:first-of-type { border-top: 0; }
.idea h3 { margin-bottom: 4px; }
.idea .why { color: var(--mute); font-size: 14px; margin-bottom: 10px; }
.price { font-weight: 600; }
.idea.gone { opacity: .45; }

.empty { color: var(--mute); text-align: center; padding: 32px 0; }

@keyframes pulse { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }
.loading { animation: pulse 1.4s ease-in-out infinite; }

@media (max-width: 560px) {
  .wrap { padding: 24px 16px 72px; }
  .row { flex-direction: column; gap: 0; }
}

/* ------------------------------------------------------------------ modal */
/* Replaces window.confirm for destructive actions. The native dialog drops out
   of the top of the window in the browser's own chrome, which reads as an error
   the page threw rather than a question the app is asking — and it blocks the
   page's event loop, which also freezes any browser automation driving it. */
.modal-scrim {
  position: fixed; inset: 0; background: var(--scrim);
  display: flex; align-items: center; justify-content: center;
  padding: 20px; z-index: 50;
}
.modal {
  background: var(--card); color: var(--ink);
  border: 1px solid var(--rule); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 22px 22px 18px;
  width: 100%; max-width: 400px;
}
.modal h3 { margin: 0 0 8px; font-size: 17px; }
.modal p { margin: 0 0 18px; color: var(--mute); font-size: 14px; line-height: 1.5; }
.modal .actions { justify-content: flex-end; }
/* The destructive choice is filled, so it is unmistakable which button does the
   irreversible thing — but focus starts on Cancel, so a stray Return is safe. */
button.wreck {
  background: var(--bad); color: var(--card); border-color: var(--bad);
}
button.wreck:hover { filter: brightness(1.08); }
@media (max-width: 560px) {
  .modal .actions { flex-direction: column-reverse; }
  .modal .actions button { width: 100%; }
}
