/* ==========================================================================
   Through Your Eyes — guest stylesheet
   Surbhi & Rahul · wedding/assets/css/style.css

   HOW THIS FILE IS ORGANISED (beginner friendly)
   ------------------------------------------------------------------------
    1. Design tokens (:root)      — the shared colours, fonts and sizes
    2. Reset & page shell         — sane defaults, safe-area padding
    3. Base typography            — headings, paragraphs, links
    4. Small utilities            — .visually-hidden, .eyebrow, .rule, .monogram
    5. Steps & motion             — the four stacked screens, fade + rise
    6. Hero screen                — #stepHero
    7. Buttons                    — .btn / .btn-primary / .btn-ghost
    8. Form fields                — #guestName, #eventSelect
    9. Drop zone                  — #dropZone, #pickBtn
   10. Preview list               — #previewList thumbnails
   11. Selected count             — #selCount
   12. Error list                 — #formErrors
   13. Progress screen            — #stepUploading
   14. Success screen             — #stepDone
   15. Footer & noscript
   16. Focus rings & accessibility
   17. Larger screens             — 390px / 430px / 768px / 1100px
   18. Reduced motion & short screens

   RULES OF THE HOUSE: ivory ground, editorial serif display type, generous
   whitespace, hairline rules, restrained gold. No gradients. No bright
   colour. No emoji. Nothing ever scrolls sideways.

   The fonts are loaded with a <link> tag in index.php — never with @import.
   ========================================================================== */


/* ==========================================================================
   1. DESIGN TOKENS
   These custom properties are SHARED with admin/admin.css. Do not rename
   them; other files depend on the exact spelling.
   ========================================================================== */

:root{
  --ivory:#FBF8F3; --paper:#FFFFFF; --sand:#F4EEE4; --beige:#EDE4D7;
  --champagne:#D9C4A0; --gold:#B08D57; --gold-soft:#C8AE84; --gold-deep:#8A6B3D;
  --charcoal:#221F1C; --ink:#3E3833; --muted:#7A6F63; --line:#E6DCCD;
  --danger:#9E4B3F; --ok:#5F7A5A;
  --font-display:'Cormorant Garamond','Cormorant',Georgia,'Times New Roman',serif;
  --font-sans:'Jost','Helvetica Neue',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif;
  --r-sm:6px; --r-md:12px; --r-lg:20px;
  --shadow-1:0 1px 2px rgba(34,31,28,.05), 0 8px 24px rgba(34,31,28,.06);
  --shadow-2:0 2px 6px rgba(34,31,28,.08), 0 18px 48px rgba(34,31,28,.10);
  --ease:cubic-bezier(.22,.61,.36,1);
  --tap:48px;

  /* Layout helpers used only by this guest stylesheet. */
  --gutter:24px;                 /* side padding on the smallest phones */
  --shell:520px;                 /* reading width of the page */
  --speed:280ms;                 /* default transition length */

  /* Always render light. iOS dark mode must NOT invert this page. */
  color-scheme:light;
}


/* ==========================================================================
   2. RESET & PAGE SHELL
   ========================================================================== */

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

html{
  /* max-width + overflow-x guarantee there is never a sideways scrollbar. */
  max-width:100%;
  overflow-x:hidden;
  background:var(--ivory);
  color-scheme:light;
  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
}

/* index.php writes <body class="guest-page">; the class is listed here so it
   resolves, and so admin pages can never pick these rules up by accident. */
body,
.guest-page{
  max-width:100%;
  overflow-x:hidden;
  margin:0;
  background:var(--ivory);
  color:var(--ink);
  font-family:var(--font-sans);
  font-size:16px;
  font-weight:300;
  line-height:1.65;
  letter-spacing:.005em;
  /* Digits as digits (lining figures): Cormorant/serif old-style
     figures elsewhere make a lone 1 look like a small I. Applied on
     body so it inherits everywhere, including inside the serif headings. */
  font-variant-numeric:lining-nums;
  -webkit-font-feature-settings:"lnum" 1;
  font-feature-settings:"lnum" 1;
  overflow-wrap:break-word;
  word-wrap:break-word;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
  min-height:100vh;
  min-height:100svh;   /* iOS: the small viewport, so toolbars do not force a scroll */
}

/* Media never pushes the layout wider than the screen. */
img,
svg,
video,
canvas{
  max-width:100%;
  height:auto;
  border:0;
}

/* Form controls inherit the page type and stay light in iOS dark mode. */
input,
select,
button,
textarea{
  font:inherit;
  color:inherit;
  color-scheme:light;
  max-width:100%;
}

button{
  cursor:pointer;
}

button[disabled],
button:disabled{
  cursor:default;
}

/* The JavaScript hides the inactive screens with the hidden attribute.
   !important is needed because the id rules below set display:flex. */
.form-actions-secondary[hidden]{
  display:none!important;
}

[hidden]{
  display:none !important;
}

::selection{
  background:var(--champagne);
  color:var(--charcoal);
}

/* ---- The page shell -----------------------------------------------------
   One narrow ivory column, centred, with safe-area aware padding so the
   iPhone notch / home indicator never sits on top of the content.

   Three elements share that column: <header class="page-head">, <main
   class="steps"> and <footer class="page-foot">. The header is the first
   thing on the page, so it — and not main — carries the notch inset.    */

.page{
  display:block;
  width:100%;
  max-width:100%;
}

.page-head{
  display:block;
  width:100%;
  max-width:var(--shell);
  margin:0 auto;
  padding-top:calc(28px + env(safe-area-inset-top));
  padding-bottom:0;
  padding-left:var(--gutter);
  padding-right:var(--gutter);
}

main,
.steps{
  display:block;
  width:100%;
  max-width:var(--shell);
  margin:0 auto;
  padding-top:28px;              /* the notch inset lives on .page-head */
  padding-bottom:calc(32px + env(safe-area-inset-bottom));
  padding-left:var(--gutter);
  padding-right:var(--gutter);
}

@supports (padding:max(0px)){
  .page-head,
  main,
  .steps{
    padding-left:max(var(--gutter), env(safe-area-inset-left));
    padding-right:max(var(--gutter), env(safe-area-inset-right));
  }
}


/* ==========================================================================
   3. BASE TYPOGRAPHY
   Display type is Cormorant Garamond (light, tight, a whisper of tracking).
   Everything else is Jost at weight 300.
   ========================================================================== */

h1,
h2,
h3{
  margin:0;
  font-family:var(--font-display);
  font-weight:300;
  font-optical-sizing:auto;
  color:var(--charcoal);
  line-height:1.08;
  letter-spacing:.012em;
}

h1{
  font-size:clamp(2.9rem, 13.2vw, 4rem);
}

h2{
  font-size:clamp(2.1rem, 9.5vw, 2.9rem);
  line-height:1.12;
}

h3{
  font-size:1.35rem;
}

p{
  margin:0 0 1.1em;
}

p:last-child{
  margin-bottom:0;
}

a{
  color:var(--gold);
  text-decoration:none;
  border-bottom:1px solid var(--line);
  transition:border-color var(--speed) var(--ease), color var(--speed) var(--ease);
}

a:hover{
  color:var(--charcoal);
  border-bottom-color:var(--gold-soft);
}

strong,
b{
  font-weight:500;
}

small{
  font-size:.82em;
}


/* ==========================================================================
   4. SMALL UTILITIES
   ========================================================================== */

/* ---- Hidden from eyes, still read aloud by screen readers -------------- */
.visually-hidden{
  position:absolute !important;
  width:1px;
  height:1px;
  padding:0;
  margin:-1px;
  overflow:hidden;
  clip:rect(0 0 0 0);
  clip-path:inset(50%);
  white-space:nowrap;
  border:0;
}

/* ---- The letterspaced small-caps label used above sections ------------- */
.eyebrow{
  display:block;
  margin:0 0 14px;
  font-family:var(--font-sans);
  font-size:11px;
  font-weight:400;
  line-height:1.6;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--muted);
}

/* ---- Hairline rule with a tiny gold diamond in the middle -------------- */
hr,
.rule{
  position:relative;
  display:block;
  width:100%;
  max-width:200px;
  height:1px;
  margin:26px auto;
  padding:0;
  border:0;
  background:var(--line);
  overflow:visible;
}

hr::after,
.rule::after{
  content:"";
  position:absolute;
  top:-3px;
  left:50%;
  width:5px;
  height:5px;
  margin-left:-3px;
  transform:rotate(45deg);
  background:var(--ivory);
  border:1px solid var(--champagne);
}

/* ---- The monogram mark -------------------------------------------------
   A thin champagne ring with the couple's initials (or a small glyph)
   inside. Works with plain text, an <svg> or an <img>.

   THE RING IS DRAWN HERE, ONCE. index.php wraps its ampersand svg in
   <span class="monogram"> and that svg must never draw a circle of its
   own, or the mark shows two of them.                                   */
.monogram{
  display:flex;
  align-items:center;
  justify-content:center;
  width:58px;
  height:58px;
  margin:0 auto 22px;
  padding:0;
  border:1px solid var(--champagne);
  border-radius:50%;
  background:transparent;
  font-family:var(--font-display);
  font-size:17px;
  font-weight:400;
  line-height:1;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--gold);
}

/* The mark inside the ring. Sized in em so it follows the ring's own
   font-size at every breakpoint below (17px -> 46px, like the svg's own
   width/height attributes; 19px -> 51px; 14px -> 38px). */
.monogram svg,
.monogram img{
  display:block;
  width:2.7em;
  height:2.7em;
}


/* ==========================================================================
   5. STEPS & MOTION
   index.php stacks four <section> screens inside <main>. JavaScript adds
   .is-active to the visible one and the hidden attribute to the others.
   ========================================================================== */

/* All four screens carry class="step"; three of them are also centred
   flex columns (below), and #stepForm is a plain block. */
.step{
  width:100%;
  margin:0;
}

#stepHero,
#stepUploading,
#stepDone{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  min-height:64vh;
  text-align:center;
}

#stepForm{
  display:block;
  text-align:left;
}

/* Fade + a small rise when a screen becomes the active one. */
.is-active{
  animation:wedRise 420ms var(--ease) both;
}

@keyframes wedRise{
  from{ opacity:0; transform:translateY(10px); }
  to  { opacity:1; transform:translateY(0); }
}


/* ==========================================================================
   6. HERO SCREEN (#stepHero)
   ========================================================================== */

.hero-title{
  margin:0 0 22px;
  font-family:var(--font-display);
  font-weight:300;
  font-optical-sizing:auto;
  font-size:clamp(3rem, 13.6vw, 4.25rem);
  line-height:.98;              /* tight editorial leading */
  letter-spacing:.015em;        /* a subtle, deliberate tracking */
  color:var(--charcoal);
  text-wrap:balance;
}

.hero-lede{
  max-width:30ch;
  margin:0 auto 18px;
  font-size:16px;
  font-weight:300;
  line-height:1.8;
  letter-spacing:.012em;
  color:var(--ink);
}

/* The couple's name sits inside the second lede paragraph. */
.hero-couple{
  display:inline-block;
  margin-top:6px;
  font-family:var(--font-display);
  font-size:1.4em;
  font-weight:400;
  font-style:italic;
  line-height:1.3;
  letter-spacing:.01em;
  color:var(--charcoal);
}

/* The paragraph holding the couple's name may use the full width. */
.hero-lede.hero-lede-couple{
  max-width:none;
}

/* "No sign-in required" */
.hero-note{
  margin:18px 0 0;
  font-size:11px;
  font-weight:300;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
}

/* The hero call to action gets extra air above it. */
#heroCta{
  margin-top:34px;
}


/* ==========================================================================
   7. BUTTONS
   Every button carries class="btn" plus .btn-primary or .btn-ghost.
   (Ids are deliberately NOT in this base rule: an id would outrank the
   .btn-primary fill and turn the main button transparent.) Min height 48px
   (--tap) and buttons are full width on phones for an easy thumb reach.
   ========================================================================== */

.btn{
  display:flex;
  align-items:center;
  justify-content:center;
  width:100%;
  min-height:var(--tap);
  padding:14px 26px;
  margin:0;
  border:1px solid transparent;
  border-radius:var(--r-sm);
  background:transparent;
  font-family:var(--font-sans);
  font-size:13.5px;
  font-weight:400;
  line-height:1.25;
  letter-spacing:.07em;
  text-align:center;
  text-decoration:none;
  color:var(--ink);
  -webkit-appearance:none;
  appearance:none;
  -webkit-tap-highlight-color:transparent;
  transition:background-color var(--speed) var(--ease),
             color var(--speed) var(--ease),
             border-color var(--speed) var(--ease),
             box-shadow var(--speed) var(--ease),
             transform 180ms var(--ease);
}

/* ---- Solid charcoal button --------------------------------------------- */
.btn{
  background:var(--charcoal);
  border-color:var(--charcoal);
  color:var(--ivory);
}

.btn:hover{
  background:#2C2824;
  border-color:#2C2824;
}

/* ---- The main call to action: charcoal with a champagne inner hairline -- */
.btn-primary{
  position:relative;
  background:var(--charcoal);
  border-color:var(--charcoal);
  color:var(--ivory);
  box-shadow:var(--shadow-1);
}

.btn-primary::after{
  content:"";
  position:absolute;
  top:4px;
  right:4px;
  bottom:4px;
  left:4px;
  border:1px solid var(--champagne);
  border-radius:3px;
  opacity:.45;
  pointer-events:none;
}

.btn-primary:hover{
  background:#2C2824;
  border-color:#2C2824;
}

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

/* ---- Outlined button ---------------------------------------------------- */
.btn-ghost{
  background:transparent;
  border-color:var(--line);
  color:var(--ink);
}

.btn-ghost:hover{
  border-color:var(--gold-soft);
  background:rgba(217,196,160,.10);
  color:var(--charcoal);
}

/* ---- Quiet text buttons: "Add more" and "Clear all" --------------------
   index.php gives both buttons class="btn btn-ghost", so these rules match
   on the id alone — an id always outranks those two classes.           */
#addMoreBtn,
#clearBtn{
  display:inline-flex;
  width:auto;
  min-width:0;               /* .btn asks for 260px on tablets; not here */
  min-height:var(--tap);
  padding:12px 2px;
  margin-right:22px;
  border:0;
  border-bottom:1px solid transparent;
  border-radius:0;
  background:none;
  font-size:11px;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
  box-shadow:none;
}

#addMoreBtn:hover,
#clearBtn:hover{
  background:none;
  color:var(--charcoal);
  border-bottom-color:var(--champagne);
}

#clearBtn{
  margin-right:0;
}

/* ---- Disabled -----------------------------------------------------------
   The submit button is disabled the moment it is pressed, so this state
   must still read as calm and intentional.                              */
.btn[disabled],
.btn:disabled,
button[disabled],
button:disabled{
  opacity:.45;
  box-shadow:none;
  transform:none;
}

button[disabled]:hover,
button:disabled:hover{
  background:var(--charcoal);
  border-color:var(--charcoal);
}

#addMoreBtn:disabled:hover,
#clearBtn:disabled:hover,
.btn-ghost:disabled:hover,
#pickBtn:disabled:hover,
#retryBtn:disabled:hover,
#doneBtn:disabled:hover{
  background:transparent;
  border-color:var(--line);
  color:var(--ink);
}

/* ---- The paragraphs that hold nothing but buttons ----------------------
   index.php wraps its buttons in <p class="hero-actions">, <p
   class="form-actions">, <p class="done-actions"> and <p id="retryWrap"
   class="retry-wrap">. Under the base p{} rule they are prose: inside the
   centred flex columns they shrink to the width of their own (empty) text,
   which starves the width:100% buttons inside them. They are layout, so
   they are told so here. The buttons keep their own 48px min-height and
   their own max-width. */
.hero-actions,
.form-actions,
.done-actions,
.retry-wrap{
  display:flex;
  flex-direction:column;
  width:100%;
  max-width:none;
  margin:0;
  padding:0;
}

/* On the three centred screens the buttons stay centred — and are NOT
   stretched, so the 768px rule that lets them shrink to 260px still
   works. */
.hero-actions,
.done-actions,
.retry-wrap{
  align-items:center;
}

/* The form screen is a left-aligned column, so its button starts at the
   left edge like every field above it. Air between the notices and
   "Share These Moments". */
.form-actions{
  align-items:stretch;
  margin-top:26px;
}

/* Spacing when buttons stack vertically on a screen. */
#stepDone button{
  margin-top:12px;
}

#stepDone button:first-of-type{
  margin-top:0;
}


/* ==========================================================================
   8. FORM FIELDS (#guestName, #eventSelect)
   Font size is 16px on purpose: anything smaller makes iOS Safari zoom in
   when the field is tapped.
   ========================================================================== */

#uploadForm,
.form{
  margin:0;
}

.field{
  margin:0 0 22px;
}

/* Labels share the eyebrow treatment. */
#uploadForm label,
.field label,
.label{
  display:block;
  margin:0 0 9px;
  font-family:var(--font-sans);
  font-size:11px;
  font-weight:400;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--muted);
}

/* The hidden file input must never pick up label styling. */
#uploadForm label.visually-hidden{
  margin:0;
}

#guestName,
#eventSelect,
.input,
.select,
input[type="text"],
input[type="search"],
input[type="email"],
textarea,
select{
  display:block;
  width:100%;
  min-height:var(--tap);
  padding:13px 16px;
  border:1px solid var(--line);
  border-radius:var(--r-sm);
  background-color:var(--paper);
  font-family:var(--font-sans);
  font-size:16px;
  font-weight:300;
  line-height:1.4;
  letter-spacing:.01em;
  color:var(--ink);
  -webkit-appearance:none;
  appearance:none;
  transition:border-color var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}

/* Placeholders carry no fading: --muted at full strength is 4.63:1 on the
   ivory page and 4.90:1 on the paper field, both past WCAG AA. Firefox
   dims placeholders by default, so opacity is set on purpose. */
#guestName::placeholder,
.input::placeholder,
input::placeholder,
textarea::placeholder{
  color:var(--muted);
  opacity:1;
  font-weight:300;
  letter-spacing:.02em;
}

#guestName:hover,
#eventSelect:hover,
.input:hover,
.select:hover,
select:hover{
  border-color:var(--champagne);
}

#guestName:focus,
#eventSelect:focus,
.input:focus,
.select:focus,
input:focus,
select:focus,
textarea:focus{
  border-color:var(--gold-soft);
  box-shadow:0 0 0 3px rgba(217,196,160,.18);
}

/* ---- The native select, with our own chevron ---------------------------
   We only repaint the arrow. The element stays a real <select>, so iOS
   still opens its native wheel picker and Android its own list.         */
#eventSelect,
.select,
select{
  padding-right:46px;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6' fill='none' stroke='%23B08D57' stroke-width='1.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 17px center;
  background-size:12px 8px;
  cursor:pointer;
  text-overflow:ellipsis;
}

/* Remove the extra arrow older Internet Explorer / Edge painted. */
select::-ms-expand{
  display:none;
}

/* Until a celebration is picked, the placeholder option reads as muted. */
#eventSelect option[value=""]{
  color:var(--muted);
}


/* ==========================================================================
   9. DROP ZONE (#dropZone)
   A hairline-framed panel. On phones it is really just a big friendly
   target for #pickBtn; on desktop it also accepts dragged files.
   ========================================================================== */

#dropZone,
.dropzone{
  position:relative;
  display:block;
  padding:30px 20px;
  margin:0 0 4px;
  border:1px dashed var(--line);
  border-radius:var(--r-md);
  background:var(--paper);
  text-align:center;
  transition:border-color var(--speed) var(--ease), background-color var(--speed) var(--ease);
}

/* "Photos and videos, straight from your camera roll." — it sits UNDER
   #pickBtn, so the air goes above it. */
.dropzone-hint{
  margin:16px 0 0;
  font-size:13.5px;
  line-height:1.6;
  color:var(--muted);
}

/* #pickBtn sits inside the zone and should not stretch edge to edge. */
#dropZone #pickBtn{
  max-width:300px;
  margin:0 auto;
}

/* Dragging files over the zone. app.js writes exactly one class here:
   'is-dragover' (see the dragenter / dragleave / drop handlers). */
#dropZone.is-dragover,
.dropzone.is-dragover{
  border-color:var(--gold-soft);
  border-style:solid;
  background:var(--sand);
}

/* Keyboard users see the zone highlight too. */
#dropZone:focus-within{
  border-color:var(--champagne);
}


/* ==========================================================================
   10. PREVIEW LIST (#previewList)
   Three square thumbnails per row on a phone, with the remove button in
   the top-right corner and the file name + size underneath.
   ========================================================================== */

#previewList,
.preview-list{
  display:grid;
  grid-template-columns:repeat(3, minmax(0, 1fr));
  gap:10px;
  list-style:none;
  margin:20px 0 0;
  padding:0;
}

#previewList:empty{
  margin:0;
}

#previewList > li,
#previewList .preview-item{
  position:relative;
  min-width:0;               /* lets long file names shrink, not overflow */
  margin:0;
  padding:0;
  text-align:left;
  animation:wedRise 280ms var(--ease) both;
}

/* ---- The square media box ---------------------------------------------
   app.js builds exactly one shape: <div class="preview-media"> holding
   either <img class="preview-thumb"> or the .preview-ph tile.          */
#previewList > li > .preview-media{
  position:relative;
  display:block;
  width:100%;
  aspect-ratio:1 / 1;
  margin:0;
  overflow:hidden;
  border:1px solid var(--line);
  border-radius:var(--r-sm);
  background:var(--sand);
}

/* Fallback for older iOS Safari without aspect-ratio: the padding trick. */
@supports not (aspect-ratio: 1 / 1){
  #previewList > li > .preview-media{
    height:0;
    padding-top:100%;
  }

  #previewList > li > .preview-media > *{
    position:absolute;
    top:0;
    right:0;
    bottom:0;
    left:0;
  }
}

/* The picture itself fills the square. app.js gives it .preview-thumb. */
#previewList img,
#previewList .preview-thumb{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  background:var(--sand);
}

/* ---- Placeholder tile for videos and HEIC photos -----------------------
   Browsers usually cannot decode HEIC, and videos have no still frame, so
   the JavaScript draws a calm tile with a glyph and the extension.
   The class names here are the ones app.js really writes: .preview-ph
   plus .preview-ph-photo or .preview-ph-video.                        */
#previewList .preview-ph{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  width:100%;
  height:100%;
  background:var(--sand);
  color:var(--muted);
  text-align:center;
}

/* Margin, not flex `gap`: older iOS Safari does not gap a flex box. */
#previewList .preview-ph svg{
  display:block;
  width:22px;
  height:22px;
  margin:0 0 6px;
  stroke:var(--gold);
  fill:none;
  opacity:.9;
}

/* A photo we could not decode sits on paper; a video sits on sand, so the
   two kinds of tile are told apart at a glance without any colour. */
#previewList .preview-ph-photo{
  background:var(--paper);
}

#previewList .preview-ph-video{
  background:var(--sand);
}

#previewList .preview-ext{
  display:block;
  font-size:10px;
  font-weight:400;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--ink);
}

/* ---- Remove button in the corner ---------------------------------------
   The visible circle is 32px so it does not swallow the thumbnail, but an
   invisible pseudo-element stretches the tap area to a full 48px.      */
#previewList button,
.preview-remove{
  position:absolute;
  top:5px;
  right:5px;
  z-index:2;
  display:flex;
  align-items:center;
  justify-content:center;
  width:32px;
  height:32px;
  min-height:0;
  padding:0;
  border:0;
  border-radius:50%;
  background:rgba(34,31,28,.58);
  color:var(--ivory);
  font-family:var(--font-sans);
  font-size:15px;
  font-weight:300;
  line-height:1;
  letter-spacing:0;
  -webkit-tap-highlight-color:transparent;
  transition:background-color var(--speed) var(--ease);
}

#previewList button::after,
.preview-remove::after{
  /* Invisible 48x48 touch target, centred on the little circle. */
  content:"";
  position:absolute;
  top:50%;
  left:50%;
  width:var(--tap);
  height:var(--tap);
  margin:calc(var(--tap) / -2) 0 0 calc(var(--tap) / -2);
}

#previewList button:hover,
.preview-remove:hover{
  background:var(--charcoal);
}

#previewList button svg,
.preview-remove svg{
  width:11px;
  height:11px;
  stroke:currentColor;
  fill:none;
}

/* ---- File name and size beneath the square ----------------------------- */
#previewList .preview-meta,
#previewList .preview-name,
#previewList .preview-size{
  display:block;
  margin:6px 0 0;
  overflow:hidden;
  font-size:11px;
  line-height:1.45;
  letter-spacing:.01em;
}

#previewList .preview-meta{
  margin-top:6px;
}

#previewList .preview-name{
  color:var(--ink);
  white-space:nowrap;
  text-overflow:ellipsis;
}

#previewList .preview-size{
  margin-top:1px;
  font-size:10.5px;
  letter-spacing:.06em;
  color:var(--muted);
}

/* The reason one file did not make it. JavaScript keeps it hidden until
   there is something to say (see [hidden] in §2), so it takes no room on
   a happy upload. */
#previewList .preview-status{
  display:block;
  margin-top:3px;
  font-size:10.5px;
  line-height:1.5;
  letter-spacing:.02em;
  color:var(--danger);
  overflow-wrap:anywhere;
}

/* ---- Per-file status ----------------------------------------------------
   app.js writes 'preview-item is-' + status, where status is one of
   pending | uploading | done | error. All four are answered here. */
#previewList > li.is-pending .preview-media{
  opacity:1;                 /* chosen, waiting its turn: the calm default */
  border-color:var(--line);
}

#previewList > li.is-uploading .preview-media{
  opacity:.65;
}

#previewList > li.is-done .preview-media{
  border-color:var(--ok);
}

#previewList > li.is-error .preview-media{
  border-color:var(--danger);
}

#previewList > li.is-error .preview-name{
  color:var(--danger);
}


/* ==========================================================================
   11. SELECTED COUNT (#selCount)
   ========================================================================== */

#selCount,
.sel-count{
  display:block;
  margin:16px 0 0;
  font-family:var(--font-sans);
  font-size:11px;
  font-weight:400;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--muted);
}

#selCount:empty{
  display:none;
}

/* The row that holds "Add more" / "Clear all" (index.php calls it
   .form-actions-secondary). The two buttons sit side by side, not stacked. */
.form-actions-secondary{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  margin:4px 0 0;
}


/* ==========================================================================
   12. ERROR LIST (#formErrors)
   Friendly, quiet, never alarming. One hairline rule in the danger tone.
   ========================================================================== */

#formErrors,
.form-errors{
  margin:18px 0 0;
  padding:0;
  list-style:none;
}

#formErrors:empty{
  display:none;
  margin:0;
}

#formErrors ul{
  margin:0;
  padding:0;
  list-style:none;
}

/* One message. JavaScript writes these as <p class="form-error-msg">. */
#formErrors p,
#formErrors .form-error-msg{
  margin:0 0 8px;
  padding:11px 14px;
  border:1px solid rgba(158,75,63,.22);
  border-left:2px solid var(--danger);
  border-radius:var(--r-sm);
  background:rgba(158,75,63,.045);
  font-size:13px;
  line-height:1.55;
  letter-spacing:.01em;
  color:var(--danger);
  overflow-wrap:anywhere;
}

/* The file names that belong to the message above them: quiet, unboxed,
   and indented to the same place as the text inside the box. */
#formErrors .form-error-list{
  margin:0 0 8px;
  padding:0 14px;
  list-style:none;
}

#formErrors .form-error-list li{
  margin:0;
  font-size:12px;
  line-height:1.6;
  letter-spacing:.01em;
  color:var(--muted);
  overflow-wrap:anywhere;
}

#formErrors p:last-child,
#formErrors .form-error-list:last-child{
  margin-bottom:0;
}


/* ==========================================================================
   13. PROGRESS SCREEN (#stepUploading)
   A hairline track with a charcoal fill, a large serif percentage and one
   supporting line beneath it.
   ========================================================================== */

/* ---- "Uploading your memories... 42%" ---------------------------------
   index.php keeps the sentence and the number in ONE paragraph:

     <p class="uploading-line">Uploading your memories... <span
        id="progressPct">0%</span></p>

   app.js reads that sentence out of the markup and then writes the bare
   number into #progressPct (see pctNeedsLabel), so the words must stay in
   the HTML. The paragraph is the quiet label; #progressPct below is the
   big display number. */
.uploading-line{
  display:block;
  margin:0;
  font-family:var(--font-sans);
  font-size:11px;
  font-weight:400;
  line-height:1.6;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--muted);
}

/* The big number, in the display serif. Tabular figures stop it jittering
   as the percentage climbs. */
#progressPct{
  display:block;
  margin:14px 0 20px;           /* 14px of air under the label above it */
  font-family:var(--font-display);
  font-weight:300;
  font-optical-sizing:auto;
  font-size:clamp(3.6rem, 18vw, 5.25rem);
  line-height:1;
  letter-spacing:.01em;
  color:var(--charcoal);
  font-variant-numeric:lining-nums tabular-nums;
  -webkit-font-feature-settings:"tnum" 1, "lnum" 1;
  font-feature-settings:"tnum" 1, "lnum" 1;
}

/* The track: one hairline across the column. */
#progressWrap,
.progress{
  position:relative;
  width:100%;
  max-width:340px;
  height:1px;
  margin:0 auto;
  overflow:hidden;
  background:var(--line);
  border-radius:1px;
}

/* The fill: JavaScript sets its width in percent. */
#progressBar,
.progress-bar{
  display:block;
  width:0;
  height:100%;
  min-height:1px;
  background:var(--charcoal);
  border-radius:1px;
  transition:width 320ms var(--ease);
}

/* "3 of 12 moments shared" */
#progressText,
.progress-text{
  display:block;
  margin:22px 0 0;
  font-size:11.5px;
  font-weight:300;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
}

/* "Please keep this page open until everything is shared." — the same
   quiet treatment as the line above it, one step further down the page. */
.uploading-note{
  display:block;
  margin:16px 0 0;
  font-size:11.5px;
  font-weight:300;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
}


/* ==========================================================================
   14. SUCCESS SCREEN (#stepDone)
   ========================================================================== */

#stepDone h2{
  margin:0 0 18px;
  font-size:clamp(2.4rem, 11vw, 3.2rem);
  letter-spacing:.015em;
}

/* The one sentence under the heading. This rule used to be #stepDone p,
   which also caught #resultSummary, #retryWrap and .done-actions and
   squeezed all three into 30ch — the buttons inside them included. It is
   aimed at the sentence only. */
.done-lede{
  max-width:30ch;
  margin:0 auto 14px;
  font-size:15.5px;
  line-height:1.8;
  color:var(--ink);
}

#resultSummary,
.result-summary{
  margin:20px auto 0;
  padding:18px 16px;
  max-width:340px;
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  font-size:13px;
  line-height:1.8;
  letter-spacing:.04em;
  color:var(--muted);
}

#resultSummary p{
  max-width:none;
  margin:0;
  font-size:13px;
  line-height:1.8;
  color:var(--muted);
}

/* "9 moments uploaded successfully." — the one line we want read first. */
#resultSummary .result-ok{
  font-family:var(--font-display);
  font-size:1.25em;
  font-weight:400;
  line-height:1.5;
  color:var(--charcoal);
}

/* The line about files that did not make it. */
#resultSummary .result-fail{
  margin-top:12px;
  color:var(--danger);
}

/* Which files, and why. Both come straight from the guest's device or
   from upload.php, so JavaScript writes them as plain text. */
#resultSummary .result-fail-list{
  margin:8px 0 0;
  padding:0;
  list-style:none;
  text-align:left;
}

#resultSummary .result-fail-item{
  margin:0 0 8px;
  overflow-wrap:anywhere;
}

#resultSummary .result-fail-item:last-child{
  margin-bottom:0;
}

#resultSummary .result-fail-name{
  display:block;
  font-size:12px;
  line-height:1.5;
  color:var(--ink);
}

#resultSummary .result-fail-why{
  display:block;
  font-size:11.5px;
  line-height:1.6;
  color:var(--danger);
}

/* Shown only when a file did not make it. The layout rules it shares with
   the other button wrappers are in §7; this is its own spacing. */
#retryWrap{
  margin:22px 0 0;
}

/* All the closing buttons live in one comfortable column. */
#stepDone #moreBtn,
#stepDone #doneBtn,
#stepDone #retryBtn{
  max-width:320px;
  margin-left:auto;
  margin-right:auto;
}

#stepDone #moreBtn{
  margin-top:28px;
}


/* ==========================================================================
   15. FOOTER & NOSCRIPT
   ========================================================================== */

footer,
.page-foot{
  width:100%;
  max-width:var(--shell);
  margin:0 auto;
  padding:26px var(--gutter) calc(28px + env(safe-area-inset-bottom));
  text-align:center;
  font-size:11px;
  font-weight:300;
  line-height:1.9;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--muted);
}

@supports (padding:max(0px)){
  footer,
  .page-foot{
    padding-left:max(var(--gutter), env(safe-area-inset-left));
    padding-right:max(var(--gutter), env(safe-area-inset-right));
  }
}

/* The couple's name, then the hashtag: the only two lines down here.
   Both classes are named so neither depends on the bare tag alone. */
footer p,
.foot-names,
.foot-hashtag{
  margin:0;
}

footer a,
.page-foot a{
  color:var(--muted);
  border-bottom-color:transparent;
}

footer a:hover,
.page-foot a:hover{
  color:var(--charcoal);
  border-bottom-color:var(--champagne);
}

/* The message shown when JavaScript is switched off. */
noscript{
  display:block;
}

.noscript-note{
  margin:0 0 24px;
  padding:18px 18px;
  border:1px solid var(--line);
  border-left:2px solid var(--gold);
  border-radius:var(--r-sm);
  background:var(--paper);
  font-size:14px;
  line-height:1.7;
  color:var(--ink);
  text-align:left;
}


/* ==========================================================================
   16. FOCUS RINGS & ACCESSIBILITY
   A visible gold ring on every focusable thing. The @supports block keeps
   the ring for keyboard users only on browsers that understand
   :focus-visible, while older browsers still get a ring on every focus.
   ========================================================================== */

:focus{
  outline:2px solid var(--gold-deep);
  outline-offset:3px;
}

@supports selector(:focus-visible){
  :focus:not(:focus-visible){
    outline:none;
  }

  :focus-visible{
    outline:2px solid var(--gold-deep);
    outline-offset:3px;
  }
}

/* Inside the dark buttons and on thumbnails the offset needs to be tighter
   so the ring is not clipped by the rounded corner. */
#previewList button:focus,
#previewList button:focus-visible,
.preview-remove:focus,
.preview-remove:focus-visible{
  outline-offset:2px;
}

/* The visually hidden file input still forwards focus to #pickBtn, but if
   it is ever focused directly the drop zone shows the state (see §9). */

/* Give live regions a predictable place in the flow. */
[aria-live]{
  min-height:1px;
}


/* ==========================================================================
   17. LARGER SCREENS
   Tuned first for 375px (iPhone SE / 13 mini), then 390 (iPhone 14),
   430 (iPhone Pro Max), then tablets and desktop.
   ========================================================================== */

/* ---- 390px: a touch more air ------------------------------------------- */
@media (min-width:390px){
  :root{
    --gutter:26px;
  }

  #previewList{
    gap:11px;
  }

  #dropZone{
    padding:34px 22px;
  }
}

/* ---- 430px: the large phones ------------------------------------------- */
@media (min-width:430px){
  :root{
    --gutter:28px;
  }

  body,
  .guest-page{
    font-size:16.5px;
  }

  #previewList{
    gap:12px;
  }

  #previewList .preview-name{
    font-size:11.5px;
  }

  #dropZone{
    padding:38px 24px;
  }

  .page-head{
    padding-top:calc(34px + env(safe-area-inset-top));
  }

  main,
  .steps{
    padding-top:34px;
  }
}

/* ---- 600px: small tablets, four thumbnails fit comfortably ------------- */
@media (min-width:600px){
  #previewList{
    grid-template-columns:repeat(4, minmax(0, 1fr));
    gap:14px;
  }
}

/* ---- 768px: tablets ----------------------------------------------------- */
@media (min-width:768px){
  :root{
    --gutter:40px;
    --shell:600px;
  }

  main,
  .steps{
    padding-top:64px;
    padding-bottom:72px;
  }

  h1,
  .hero-title{
    font-size:4.6rem;
  }

  .hero-lede{
    font-size:17px;
    max-width:34ch;
  }

  #stepHero,
  #stepUploading,
  #stepDone{
    min-height:70vh;
  }

  /* Buttons no longer need to span the whole column. */
  .btn,
  #heroCta,
  #pickBtn,
  #retryBtn,
  #moreBtn,
  #doneBtn{
    width:auto;
    min-width:260px;
    padding:15px 34px;
  }

  #submitBtn{
    width:100%;
    max-width:320px;
    padding:15px 34px;
  }

  #dropZone{
    padding:46px 32px;
  }

  #previewList{
    gap:16px;
  }

  #progressWrap{
    max-width:420px;
  }

  #progressPct{
    font-size:5.5rem;
  }

  .done-lede{
    font-size:16.5px;
  }

  /* Hover lift only on devices with a real pointer. */
  @media (hover:hover) and (pointer:fine){
    .btn:hover,
    .btn-primary:hover{
      box-shadow:var(--shadow-2);
    }
  }
}

/* ---- 1100px: desktop ---------------------------------------------------- */
@media (min-width:1100px){
  :root{
    --shell:660px;
  }

  main,
  .steps{
    padding-top:84px;
    padding-bottom:92px;
  }

  h1,
  .hero-title{
    font-size:5.4rem;
    letter-spacing:.018em;
  }

  .hero-lede{
    font-size:17.5px;
    line-height:1.85;
  }

  .hero-couple{
    font-size:1.55em;
  }

  #previewList{
    grid-template-columns:repeat(5, minmax(0, 1fr));
    gap:18px;
  }

  #progressPct{
    font-size:6rem;
  }

  #stepDone h2{
    font-size:3.6rem;
  }

  .monogram{
    width:64px;
    height:64px;
    font-size:19px;
  }
}


/* ==========================================================================
   18. SHORT SCREENS & REDUCED MOTION
   ========================================================================== */

/* A phone held in landscape has very little height — pull the vertical
   centring back so nothing is cut off. */
@media (max-height:620px){
  #stepHero,
  #stepUploading,
  #stepDone{
    min-height:0;
    justify-content:flex-start;
  }

  .hero-title{
    font-size:2.6rem;
  }

  #progressPct{
    font-size:3.4rem;
  }

  .monogram{
    width:46px;
    height:46px;
    margin-bottom:16px;
    font-size:14px;
  }
}

/* Some guests ask their phone to reduce motion. Honour that completely. */
@media (prefers-reduced-motion: reduce){
  *,
  *::before,
  *::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    transition-delay:0ms !important;
    scroll-behavior:auto !important;
  }

  .is-active,
  #previewList > li{
    animation:none !important;
    opacity:1;
    transform:none;
  }

  .btn-primary:active,
  #heroCta:active,
  #submitBtn:active,
  #moreBtn:active{
    transform:none;
  }
}

/* Windows high-contrast / forced colours: keep the outlines meaningful. */
@media (forced-colors: active){
  .btn,
  .btn-primary,
  .btn-ghost,
  #previewList > li > .preview-media,
  #progressWrap{
    border:1px solid;
  }

  #progressBar{
    background:CanvasText;
  }
}


/* ==========================================================================
   EMBLEM  — the camera-and-heart artwork above the hero.
   .monogram--logo sits on the same wrapper as the old ampersand seal, so
   every spacing rule still applies, but the circle, border and fixed
   58px box are switched off and the image sets its own size.
   The doubled class (.monogram.monogram--logo) is deliberate: it outranks
   the width/height overrides inside the media queries above.
   ========================================================================== */
.monogram.monogram--logo{
  width:auto;
  height:auto;
  padding:0;
  border:0;
  border-radius:0;
  background:transparent;
  box-shadow:none;
}

.monogram.monogram--logo img{
  display:block;
  width:172px;
  max-width:72vw;
  height:auto;
  margin:0 auto;
}

@media (min-width:430px){
  .monogram.monogram--logo img{ width:196px; }
}

@media (min-width:768px){
  .monogram.monogram--logo img{ width:220px; }
}


/* ==========================================================================
   BACK CONTROL
   A quiet way out of the upload form, back to the welcome screen. Deliberately
   understated — it should be findable, not attention-seeking — but still a
   full 48px tall so it is comfortable to tap with a thumb.
   ========================================================================== */
.step-back{
  margin:0 0 18px;
  text-align:left;
}

.btn-back{
  display:inline-flex;
  align-items:center;
  gap:8px;
  min-height:var(--tap);
  margin:0;
  padding:12px 2px;
  border:0;
  background:none;
  font-family:var(--font-sans);
  font-size:11px;
  font-weight:400;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
  cursor:pointer;
  -webkit-appearance:none;
  appearance:none;
  -webkit-tap-highlight-color:transparent;
  transition:color var(--speed) var(--ease);
}

.btn-back:hover,
.btn-back:focus-visible{
  color:var(--charcoal);
}

.btn-back span{
  font-size:15px;
  line-height:1;
}
