/*
 * hub.css — Shared base stylesheet for all Brewtec Hub LIFF forms.
 *
 * How to use:
 *   This file is the canonical source. Each form (sales-report, checklist,
 *   inventory) copies it into its own folder at build time. Do NOT load it via a
 *   cross-folder <link href> — Cloudflare Pages deploys each folder independently.
 *
 * Covers:
 *   - LINE-native LIGHT moodboard (white background, #06C755 LINE green accent).
 *   - Form field baseline: text inputs, number inputs, checkboxes, button pickers.
 *   - Button-row picker pattern (replaces dropdown <select> for staff selection).
 *   - Collapsible section pattern (used by Inventory).
 *   - Sticky footer with safe-area-inset-bottom padding (R6 — Android edge-to-edge).
 *   - Auto-save status line.
 *   - Soft-warning style (used for calc≠POS mismatch, needs-refill, etc.).
 *   - Large touch targets (primary action buttons).
 *   - Loading and error state helpers.
 *   - Preview-mode phone frame (active only when ?preview=1 sets body.preview-mode).
 *
 * RESEARCH CAVEAT R6 — Android edge-to-edge (rolled out March 2026):
 *   The system navigation bar can overlap content at the bottom. All sticky
 *   footers MUST use padding-bottom: calc(Npx + env(safe-area-inset-bottom)).
 *   This is applied to the .hub-footer class below.
 */

/* ── Reset & base ─────────────────────────────────────────────────────────── */

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

/* Thai + Latin font stack. Sarabun is free, has full Thai glyph coverage, and
   renders cleanly at small sizes. The Google Fonts import is in each form's
   index.html so forms can choose a CDN or a local copy. Sarabun reads visually
   thinner than Latin so we set a slightly larger base size for readability. */
html {
  font-family: 'Sarabun', 'Noto Sans Thai', system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  /* Prevent font-size from adjusting on orientation change (iOS). */
  -webkit-text-size-adjust: 100%;
}

body {
  /* Light LINE-native base: pure white page, subtle grey for surrounding canvas. */
  background-color: #FFFFFF;
  color: #1F1F1F;

  /* Prevent the body from scrolling behind the sticky footer. */
  min-height: 100dvh;    /* dvh handles the mobile browser chrome better than vh */
  padding-bottom: 0;
}

/* ── Colour tokens ─────────────────────────────────────────────────────────── */

:root {
  --color-bg:          #FFFFFF;   /* white — page background */
  --color-surface:     #F7F8FA;   /* very pale grey — card/section surface */
  --color-surface-alt: #EEF1F5;   /* one shade deeper — section headers */
  --color-accent:      #06C755;   /* LINE green — primary buttons, selected pills */
  --color-accent-dark: #05A847;   /* hover/active darker green */
  --color-accent-alt:  #FF8800;   /* orange — secondary / warning accents */
  --color-text:        #1F1F1F;   /* near-black — body text */
  --color-text-muted:  #6B7280;   /* grey — labels, placeholders */
  --color-border:      #E5E7EB;   /* very subtle border */
  --color-border-strong: #D1D5DB; /* slightly stronger border for focus */
  --color-success:     #16A34A;   /* green — success states */
  --color-error:       #DC2626;   /* red — error states */
  --color-warning:     #FF8800;   /* orange — soft warnings */

  /* Soft shadows for elevation (replacing harsh borders on most cards). */
  --shadow-card:    0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 3px rgba(15, 23, 42, 0.03);
  --shadow-elevated: 0 4px 12px rgba(15, 23, 42, 0.06);

  /* Touch target minimum (WCAG 2.5.5 recommends 44px). */
  --touch-target: 44px;
}

/* ── Layout helpers ────────────────────────────────────────────────────────── */

.hub-page {
  /* The main scrollable content area. Sits above the sticky footer. */
  display: flex;
  flex-direction: column;
  padding: 16px 16px 0 16px;
  /* Leave room at the bottom for the sticky footer height. Forms set this to
     the footer's computed height once it is known (or use a generous estimate). */
  padding-bottom: 140px;
}

/* ── Typography ────────────────────────────────────────────────────────────── */

h1 {
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--color-text);
  margin-bottom: 4px;
  letter-spacing: -0.005em;
}

h2 {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 10px;
  letter-spacing: -0.003em;
}

h3 {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 8px;
}

p {
  color: var(--color-text);
  margin-bottom: 8px;
  font-size: 0.95rem;
}

label {
  display: block;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--color-text-muted);
  margin-bottom: 6px;
}

/* ── Form header (date / filed-by / daily context) ─────────────────────────── */

.hub-header {
  background-color: var(--color-surface);
  border-radius: 14px;
  padding: 16px 18px;
  margin-bottom: 18px;
  box-shadow: var(--shadow-card);
}

.hub-header .date-display {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: 12px;
}

.hub-header .date-display strong {
  color: var(--color-text);
  font-size: 1rem;
  font-weight: 600;
}

/* ── Form fields ────────────────────────────────────────────────────────────── */

.hub-field {
  margin-bottom: 14px;
}

/* Text and number inputs share the same look. */
.hub-input,
.hub-number,
.hub-select,
.hub-textarea {
  width: 100%;
  min-height: var(--touch-target);
  padding: 10px 14px;
  background-color: #FFFFFF;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.95rem;
  -webkit-appearance: none;   /* remove iOS default styling */
  appearance: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.hub-input:focus,
.hub-number:focus,
.hub-select:focus,
.hub-textarea:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(6, 199, 85, 0.12);
}

.hub-input::placeholder,
.hub-number::placeholder,
.hub-textarea::placeholder {
  color: var(--color-text-muted);
  opacity: 0.6;
}

/* Number inputs: right-align the value so digits line up neatly in columns. */
.hub-number {
  text-align: right;
}

/* Select: add a custom dropdown arrow. Still present for legacy fallback —
   the new picker pattern is `.hub-picker-buttons`. */
.hub-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath fill='%236B7280' d='M0 0l6 8 6-8z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;
}

/* Textarea: allow vertical resize, keep horizontal fixed. */
.hub-textarea {
  resize: vertical;
  min-height: 72px;
}

/* ── Hidden input (used as a state holder behind button-row pickers) ──────── */

.hub-hidden-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ── Button-row picker (replaces <select> for staff name pickers) ─────────── */
/*
 * Used by Sales/Checklist/Inventory to pick a barista. Buttons are inserted by
 * the form's render*Picker() function. Horizontally scrollable if the row
 * overflows the viewport — gentler than wrapping for 3–6 short names.
 */
.hub-picker-buttons {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: 8px;
  padding: 4px 0 6px 0;
  /* Hide the horizontal scrollbar visually but keep keyboard reachability. */
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* IE/legacy Edge */
}
.hub-picker-buttons::-webkit-scrollbar {
  display: none;                  /* Safari/Chrome */
}

.hub-picker-buttons button {
  flex: 0 0 auto;
  min-height: 40px;
  padding: 8px 18px;
  background-color: #FFFFFF;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s;
}

.hub-picker-buttons button:hover,
.hub-picker-buttons button:focus {
  border-color: var(--color-accent);
  outline: none;
}

.hub-picker-buttons button.selected {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
  color: #FFFFFF;
  font-weight: 600;
  box-shadow: 0 1px 4px rgba(6, 199, 85, 0.28);
}

/* ── Checkbox rows ──────────────────────────────────────────────────────────── */

/* A checkbox task row: [ ☑ ] [ Task label ] */
.hub-checkbox-row {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: var(--touch-target);
  padding: 12px 4px;
  border-bottom: 1px solid var(--color-border);
}

.hub-checkbox-row:last-child {
  border-bottom: none;
}

/* The checkbox itself — styled so it is large enough to tap reliably. */
.hub-checkbox-row input[type="checkbox"] {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  accent-color: var(--color-accent);
  cursor: pointer;
}

.hub-checkbox-row .task-label {
  flex: 1;
  font-size: 0.95rem;
  color: var(--color-text);
  cursor: pointer;
}

/* When a task is ticked, dim the label slightly to show completion. */
.hub-checkbox-row input[type="checkbox"]:checked + .task-label {
  color: var(--color-text-muted);
  text-decoration: line-through;
  text-decoration-color: var(--color-success);
}

/* ── Stepper (1–5 score) ─────────────────────────────────────────────────────
   Used by the Checklist shot-test taste dimensions (sour, bitter, body, aroma,
   balance). Five tap targets in a row, visually highlighted on selection.       */

.hub-stepper {
  display: flex;
  gap: 6px;
}

.hub-stepper button {
  flex: 1;
  min-height: var(--touch-target);
  background-color: #FFFFFF;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  color: var(--color-text-muted);
  font-size: 1rem;
  font-family: inherit;
  cursor: pointer;
  transition: background-color 0.1s, color 0.1s, border-color 0.1s;
}

.hub-stepper button.selected {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
  color: #FFFFFF;
  font-weight: 700;
}

/* ── Collapsible sections (Inventory) ─────────────────────────────────────── */

.hub-section {
  margin-bottom: 12px;
  background-color: var(--color-surface);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.hub-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: var(--color-surface-alt);
  padding: 14px 16px;
  cursor: pointer;
  user-select: none;
}

.hub-section-header .section-title {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--color-text);
}

.hub-section-header .section-chevron {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  transition: transform 0.2s;
}

/* When the section is expanded, rotate the chevron to point up. */
.hub-section.expanded .hub-section-header .section-chevron {
  transform: rotate(180deg);
}

.hub-section-body {
  /* Hidden by default; JS toggles display on expand/collapse. */
  display: none;
  background-color: #FFFFFF;
  padding: 12px 14px;
}

.hub-section.expanded .hub-section-body {
  display: block;
}

/* ── Item rows (Inventory) ─────────────────────────────────────────────────── */

/* An inventory item row: name · unit · [unopened] · [opened] · [refilled] · [☐] */
.hub-item-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 10px;
  padding: 12px 0;
  border-bottom: 1px solid var(--color-border);
  align-items: start;
}

.hub-item-row:last-child {
  border-bottom: none;
}

.hub-item-name {
  font-size: 0.95rem;
  color: var(--color-text);
  font-weight: 500;
  align-self: center;
}

.hub-item-unit {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  margin-top: 2px;
}

/* The three count fields sit below the item name in a flex row. */
.hub-item-counts {
  display: flex;
  gap: 6px;
  margin-top: 8px;
  flex-wrap: wrap;
}

.hub-item-counts .hub-number {
  width: 72px;
  min-width: 60px;
  font-size: 0.9rem;
  padding: 8px;
}

/* The "needs refill" checkbox is right-aligned in the grid's second column. */
.hub-refill-checkbox {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  font-size: 0.72rem;
  color: var(--color-text-muted);
}

.hub-refill-checkbox input[type="checkbox"] {
  width: 22px;
  height: 22px;
  accent-color: var(--color-warning);
}

/* The "remaining %" field that appears when the needs-refill box is ticked. */
.hub-remaining-pct {
  display: none;   /* JS shows this when the checkbox is ticked */
  margin-top: 6px;
}

.hub-remaining-pct.visible {
  display: block;
}

/* ── Soft warning (mismatch, low-stock hint, etc.) ─────────────────────────── */

.hub-warning {
  background-color: rgba(255, 136, 0, 0.08);
  border: 1px solid rgba(255, 136, 0, 0.35);
  border-radius: 8px;
  padding: 10px 14px;
  margin-top: 8px;
  font-size: 0.875rem;
  color: #B45309;     /* darker amber for legible text on light bg */
}

/* ── Error message ──────────────────────────────────────────────────────────── */

.hub-error {
  background-color: rgba(220, 38, 38, 0.06);
  border: 1px solid rgba(220, 38, 38, 0.35);
  border-radius: 8px;
  padding: 12px 16px;
  margin-bottom: 12px;
  font-size: 0.9rem;
  color: var(--color-error);
}

/* ── Success / confirmation notice ─────────────────────────────────────────── */

.hub-success-banner {
  background-color: rgba(22, 163, 74, 0.06);
  border: 1px solid rgba(22, 163, 74, 0.4);
  border-radius: 12px;
  padding: 18px 20px;
  text-align: center;
  font-size: 1rem;
  color: var(--color-success);
  box-shadow: var(--shadow-card);
}

/* ── Read-only submitted/finalized notice ───────────────────────────────────── */

.hub-submitted-notice {
  background-color: var(--color-surface);
  border-radius: 14px;
  padding: 24px 20px;
  text-align: center;
  box-shadow: var(--shadow-card);
}

.hub-submitted-notice .notice-icon {
  font-size: 2.5rem;
  margin-bottom: 10px;
}

.hub-submitted-notice .notice-text {
  font-size: 0.95rem;
  color: var(--color-text);
}

/* ── Sticky footer ──────────────────────────────────────────────────────────── */
/*
 * RESEARCH CAVEAT R6 — Android edge-to-edge (March 2026 rollout):
 *   The system navigation bar can overlap the bottom of LIFF content.
 *   padding-bottom uses env(safe-area-inset-bottom) to push the footer content
 *   above the navigation bar. The base 16px ensures there is always some padding
 *   even on devices that do not report a safe-area-inset (iOS non-notch, desktop).
 */

.hub-footer {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;

  /* R6: base padding + safe-area-inset-bottom to clear the Android nav bar. */
  padding: 14px 16px calc(16px + env(safe-area-inset-bottom)) 16px;

  background-color: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid var(--color-border);
  box-shadow: 0 -4px 16px rgba(15, 23, 42, 0.04);

  /* Sit above all page content. */
  z-index: 100;
}

/* Live total line (Sales Report). */
.hub-footer .footer-total {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--color-text);
  text-align: right;
  margin-bottom: 6px;
}

/* Progress line (Checklist "7/10", Inventory flagged count). */
.hub-footer .footer-progress {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: 8px;
}

/* Auto-save status line. */
.hub-footer .footer-save-status {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  min-height: 16px;
  margin-bottom: 10px;
}

/* Row of action buttons inside the footer. */
.hub-footer .footer-buttons {
  display: flex;
  gap: 10px;
}

/* ── Buttons ────────────────────────────────────────────────────────────────── */

/* Primary button — ส่งรายงาน / เสร็จสิ้น. */
.hub-btn-primary {
  flex: 2;
  min-height: var(--touch-target);
  background-color: var(--color-accent);
  color: #FFFFFF;
  border: none;
  border-radius: 10px;
  font-family: inherit;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s, transform 0.05s, box-shadow 0.15s;
  box-shadow: 0 1px 3px rgba(6, 199, 85, 0.3);
}

.hub-btn-primary:hover,
.hub-btn-primary:focus {
  background-color: var(--color-accent-dark);
  outline: none;
}

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

.hub-btn-primary:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  box-shadow: none;
}

/* Secondary button — บันทึกร่าง. */
.hub-btn-secondary {
  flex: 1;
  min-height: var(--touch-target);
  background-color: #FFFFFF;
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background-color 0.15s;
}

.hub-btn-secondary:hover,
.hub-btn-secondary:focus {
  border-color: var(--color-accent);
  color: var(--color-accent);
  outline: none;
}

.hub-btn-secondary:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Inline/small action buttons — "+" add shot, "+ เพิ่มรายการ". */
.hub-btn-add {
  min-height: 40px;
  padding: 0 18px;
  background-color: #FFFFFF;
  color: var(--color-accent);
  border: 1px dashed var(--color-accent);
  border-radius: 999px;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.15s;
}

.hub-btn-add:hover,
.hub-btn-add:focus {
  background-color: rgba(6, 199, 85, 0.06);
  outline: none;
}

/* ── Loading spinner ────────────────────────────────────────────────────────── */

.hub-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 16px;
  gap: 14px;
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.hub-spinner {
  width: 36px;
  height: 36px;
  border: 3px solid var(--color-border);
  border-top-color: var(--color-accent);
  border-radius: 50%;
  animation: hub-spin 0.8s linear infinite;
}

@keyframes hub-spin {
  to { transform: rotate(360deg); }
}

/* ── Shot test entry (Checklist) ─────────────────────────────────────────────
   Each shot test is a collapsible card with its own set of input fields.        */

.hub-shot-entry {
  background-color: var(--color-surface);
  border-radius: 12px;
  padding: 14px;
  margin-bottom: 12px;
  box-shadow: var(--shadow-card);
}

.hub-shot-entry .shot-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.hub-shot-entry .shot-number {
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--color-text);
}

.hub-shot-remove {
  background: none;
  border: none;
  color: var(--color-error);
  font-size: 0.85rem;
  cursor: pointer;
  padding: 4px 8px;
}

/* Shot taste dimension row (label + stepper side by side). */
.hub-shot-dimension {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}

.hub-shot-dimension .dimension-label {
  flex: 0 0 80px;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.hub-shot-dimension .hub-stepper {
  flex: 1;
}

/* ── Upload / photo (Inventory Friday) ───────────────────────────────────────
   The photo control is shown only on Fridays via JS; hidden by default.         */

.hub-photo-section {
  display: none;   /* JS shows this on Fridays */
  background-color: var(--color-surface);
  border: 1px dashed var(--color-warning);
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 18px;
}

.hub-photo-section.visible {
  display: block;
}

.hub-photo-section .photo-required-label {
  font-size: 0.9rem;
  color: var(--color-warning);
  font-weight: 600;
  margin-bottom: 10px;
}

.hub-photo-preview {
  max-width: 100%;
  border-radius: 8px;
  margin-top: 10px;
  display: none;
  border: 1px solid var(--color-border);
}

.hub-photo-preview.visible {
  display: block;
}

/* ── Month-end banner (Inventory) ─────────────────────────────────────────── */

.hub-month-end-banner {
  display: none;   /* JS shows this on month-end days */
  background-color: rgba(255, 136, 0, 0.08);
  border: 1px solid rgba(255, 136, 0, 0.35);
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 18px;
  font-size: 0.9rem;
  color: #B45309;
  text-align: center;
}

.hub-month-end-banner.visible {
  display: block;
}

.hub-month-end-banner .banner-hint {
  font-size: 0.82rem;
  color: var(--color-text-muted);
}

/* ── Utility classes ─────────────────────────────────────────────────────────── */

.hidden {
  display: none !important;
}

.text-muted {
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

.text-center {
  text-align: center;
}

.mb-0 { margin-bottom: 0; }
.mb-8 { margin-bottom: 8px; }
.mb-16 { margin-bottom: 16px; }
.mt-8 { margin-top: 8px; }
.mt-16 { margin-top: 16px; }

/* ─────────────────────────────────────────────────────────────────────────────
 * PREVIEW MODE — phone-frame chrome
 *
 * Activated by liff-init.js (Layer 1.5) adding `class="preview-mode"` to <body>
 * when the page is loaded with ?preview=1. Production is byte-identical without
 * this class.
 *
 * The body becomes a centred 414px-wide phone "card" floating on a subdued grey
 * canvas — so a reviewer can see the form on a desktop as it appears on a phone.
 * ───────────────────────────────────────────────────────────────────────────── */

html:has(body.preview-mode) {
  background-color: #DEE2E8;
}

body.preview-mode {
  background-color: #FFFFFF;
  /* Centre and constrain the content like a phone screen. */
  max-width: 414px;
  margin: 24px auto;
  min-height: calc(100vh - 48px);
  box-shadow: 0 16px 48px rgba(15, 23, 42, 0.22);
  border-radius: 28px;
  overflow: hidden;
  position: relative;
  padding-top: 32px;   /* leaves room for the faux status bar drawn via ::before */
}

/* Faux status bar at the top of the phone (preview only). */
body.preview-mode::before {
  content: "9:41   •••";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  background-color: #FFFFFF;
  color: var(--color-text);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 10px 24px 6px 24px;
  text-align: right;
  border-bottom: 1px solid var(--color-border);
  z-index: 110;
}

/* In preview mode the sticky footer hugs the bottom of the "phone" card. The
   footer stays sticky at the bottom of the body — when content is short it
   sits flush with the bottom; when content scrolls, it scrolls with the body
   because the body itself is the scroll container here. */
body.preview-mode .hub-footer {
  position: sticky;
  left: 0;
  right: 0;
  bottom: 0;
  margin-top: auto;
  border-radius: 0 0 28px 28px;
}

/* Preview-mode body must be a flex column so the sticky footer can sit at the
   bottom of the phone-frame even when content is short. */
body.preview-mode {
  display: flex;
  flex-direction: column;
}
