/* =====================================================
   card-editor.css
   PURPOSE: Styles for the Card Editor screen ONLY.

   SCOPE: Everything inside #card-editor-screen.
   DO NOT put styles for other screens in this file.

   LAYOUT OVERVIEW (top to bottom):
     1. Editor header     (Back / Title / Save)
     2. Deck selector     (Save to Deck dropdown)
     3. Card side tabs    (Question / Answer)
     4. Card canvas       (The flip card itself)
     5. Confidence + Scan row  ← UPDATED
           Confidence buttons LEFT, Scan Text RIGHT,
           both on the same line
     6. Suggestion bar    ← UPDATED
           Now 2 rows tall, wraps automatically
     7. Symbol palette    (managed by symbol-palette.js)

   KEY:
     OCR  = Optical Character Recognition
     NLP  = Natural Language Processing
     CSS  = Cascading Style Sheets
     CDN  = Content Delivery Network
     JS   = JavaScript
     HTML = HyperText Markup Language
     DOM  = Document Object Model
   ===================================================== */


/* ── SCREEN WRAPPER ───────────────────────────────────
   The full card editor screen column.
   flex-direction: column stacks every section
   from top to bottom.
   gap: 10px adds space between every section. */

#card-editor-screen {
  display:        flex;
  flex-direction: column;
  gap:            10px;
  /* Fills full viewport (visible area) height so
     the palette sits anchored at the bottom */
  height:         100%;
  /* CRITICAL on shorter mobile viewports — without this, if
     everything ABOVE the palette (header, deck selector, tabs,
     the canvas's fixed 220px, confidence row, suggestion bar)
     doesn't quite fit under height: 100%, this flex column just
     overflows past that bound instead of respecting it. Since
     #screen-container (the app's real scroll region) wraps
     around this screen, THAT then becomes scrollable instead —
     letting the whole screen scroll down past the canvas to
     reach the palette, rather than the canvas staying fixed
     while only .palette-scroll's own emoji grid scrolls (see
     palette.css's "IMPORTANT SCROLL RULE" for the intended
     behavior). overflow: hidden forces this column to actually
     stay within height: 100%, so .palette-container's own
     flex: 1 + min-height: 0 (see palette.css) can do their job
     and shrink the palette to fit instead. */
  overflow:       hidden;
}

/* Hide the app-wide "RemSym" header on this screen —
   .editor-header (Back/title/Save) below already acts as
   this screen's own header, so having both stacked was
   redundant. Same :has() pattern study.css already uses
   to detect which screen is currently active. */
#app-header:has(~ #screen-container #card-editor-screen) {
  display: none;
}

/* With the app header hidden, #screen-container no longer
   needs to reserve --app-header-height of space above this
   screen's content — just the normal breathing room (and
   still the safe-area inset, for notched devices). */
#screen-container:has(#card-editor-screen) {
  padding-top: calc(16px + var(--safe-area-top));
}


/* ── EDITOR HEADER ROW ────────────────────────────────
   Contains: ← Back | deck picker <select> | Save ✓
   justify-content: space-between pushes Back to the
   left edge and Save to the right edge; the deck
   picker (styled in .editor-header__deck-select below)
   fills the space between them. */

.editor-header {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  padding-bottom:  10px;
  border-bottom:   var(--border-width) solid
                   var(--color-border);
}

/* ── DECK SELECTOR DROPDOWN ───────────────────────────
   Lets the user pick which deck a card is saved into.
   Sits in .editor-header where the deck title used to
   be — .deck-select is the base look (also usable
   elsewhere); .editor-header__deck-select overrides it
   to read like a title (bigger, centered, no visible
   field chrome) while still being a real, tappable
   <select>. */

.deck-select {
  background-color: var(--ios-tertiarySystemFill);
  color:            var(--color-text-primary);
  border:           none;
  border-radius:    var(--border-radius);
  padding:          4px 8px;
  font-size:        var(--font-size-footnote);
  cursor:           pointer;
}

.editor-header__deck-select {
  flex:             0 1 auto;
  min-width:        0;
  max-width:        140px;
  /* max-width caps the pill's width instead of letting it
     stretch across the whole space between Back and Save;
     min-width: 0 still lets a long deck name truncate
     rather than force the pill wider than that cap. */
  background-color: #fff;
  /* Solid white regardless of light/dark theme — this is
     a deliberate fixed accent so the picker reads as a
     distinct "button" against the translucent header
     bar in both themes, not something that should shift
     with --color-card-bg/--color-text-primary. */
  color:            #1a1a1a;
  border-radius:    999px;
  box-shadow:       var(--shadow-elevation-1);
  text-align:       center;
  text-align-last:  center;
  /* text-align-last = Firefox needs this specifically for
     <select>; text-align alone covers Chrome/Safari/Edge */
  font-size:        var(--font-size-subheadline);
  font-weight:      600;
  padding:          4px 12px;
  overflow:         hidden;
  text-overflow:    ellipsis;
  white-space:      nowrap;
  /* Long deck names truncate with "…" instead of
     overflowing the now-capped pill width. */
}


/* ── FRONT / BACK TAB BUTTONS ─────────────────────────
   [ Question ] [ Answer ]
   flex: 1 on each tab makes them share the full
   row width equally. */

/* iOS segmented control: a single pill-shaped track
   with a "thumb" behind whichever tab is active. Each
   side keeps its own tint color (question = orange,
   answer = green, matching the highlight-select
   feature's color coding) instead of a plain neutral
   thumb, so the active side is still identifiable at
   a glance.                                          */
.card-side-tabs {
  display:          flex;
  gap:              2px;
  padding:          2px;
  background-color: var(--ios-systemGray6);
  border-radius:    var(--radius-sm);
}

.tab-btn {
  flex:             1;
  padding:          7px 8px;
  background-color: transparent;
  border:           none;
  border-radius:    calc(var(--radius-sm) - 2px);
  color:            var(--color-text-secondary);
  cursor:           pointer;
  font-family:      var(--font-primary);
  font-size:        var(--font-size-footnote);
  font-weight:      600;
  transition:       background-color 0.2s ease,
                    color 0.2s ease;
}

/* ── ACTIVE TAB STATES ────────────────────────────────
   Each side gets its own color identity.
   Question = orange tint (matches highlight
              selector yellow = question pattern)
   Answer   = green tint (matches highlight
              selector green = answer pattern)

   card-editor.js applies these classes via
   updateTabHighlight() by checking the data-side
   attribute (data-side = an HTML (HyperText Markup
   Language = the code that structures web pages)
   data attribute set on each tab button to identify
   which card side it controls).                   */

/* Question tab — active state */
.tab-btn--active[data-side="question"] {
  background-color: var(--color-tab-question);
  color:            var(--ios-systemOrange);
}

/* Answer tab — active state */
.tab-btn--active[data-side="answer"] {
  background-color: var(--color-tab-answer);
  color:            var(--color-confidence-5);
}


/* ══════════════════════════════════════════════════════
   CARD FLIP STRUCTURE

   HOW THE 3D FLIP WORKS:

   1. .card-flip-container
      Sets the viewing perspective.
      perspective (CSS property) = simulates depth,
      like the distance from your eye to the card.

   2. .card-flip-inner
      The element that actually rotates in 3D space.
      transform-style: preserve-3d tells the browser
      to keep both card faces in the same 3D space
      so they flip together correctly.

   3. .card-face--question  (front face)
      Starts at 0deg rotation — visible by default.

   4. .card-face--answer  (back face)
      Starts at 180deg — hidden behind the front.
      Comes into view when inner rotates to 180deg.

   5. backface-visibility: hidden
      Hides the mirrored reverse side of each face
      so you never see a ghost image through the card
      while it is rotating.
   ══════════════════════════════════════════════════════ */

/* ── CARD FLIP CONTAINER ──────────────────────────────
   Outer wrapper. Sets the 3D viewing distance only.
   Does NOT rotate itself — the inner does that. */

.card-flip-container {
  perspective: 1000px;
  /* 1000px = comfortable viewing distance.
     Lower value = more dramatic perspective distortion.
     Higher value = flatter, more subtle depth effect. */
  width:       100%;
  height:      220px;  /* Fixed height prevents the card
                          from collapsing during the flip */
  position:    relative;
}

/* ── CARD FLIP INNER ──────────────────────────────────
   This element physically rotates.
   Both card faces are children of this element. */

.card-flip-inner {
  position:        relative;
  width:           100%;
  height:          100%;
  transform-style: preserve-3d;
  /* preserve-3d = keeps child elements rendered
     in the same 3D space as this parent element */
  transition:      transform 0.5s ease;
  transform:       rotateY(0deg); /* default: front visible */
}

/* Flip RIGHT → reveals the Answer face */
.card-flip-inner.flipped-right {
  transform: rotateY(180deg);
}

/* Flip LEFT → returns to the Question face.
   Uses -360deg instead of 0deg so the animation
   always moves in the LEFT (negative) direction
   and never jumps forward instead of back. */
.card-flip-inner.flipped-left {
  transform: rotateY(-180deg);
}

/* ── CARD FACE (shared by both sides) ─────────────────
   Both faces are stacked on top of each other
   using position: absolute so they occupy the
   exact same space inside the flip container. */

.card-face {
  position:               absolute;
  top:                    0;
  left:                   0;
  width:                  100%;
  height:                 100%;
  backface-visibility:    hidden;
  /* backface-visibility: hidden = hides the reversed
     mirror image of this face during rotation */
  -webkit-backface-visibility: hidden; /* Safari prefix */
  border-radius:          var(--border-radius-card);
  overflow:               visible;
}

/* Front face — visible at 0deg (default state) */
.card-face--question {
  transform: rotateY(0deg);
  z-index:   2;
}

/* Back face — hidden at 180deg until the card flips */
.card-face--answer {
  transform: rotateY(180deg);
  z-index:   1;
}

/* ── CARD CANVAS ──────────────────────────────────────
   The visible card surface on each face.
   position: relative is required so that placed
   symbols (position: absolute children) position
   themselves relative to this card, not the page. */

.card-canvas {
  position:         relative;
  background-color: var(--color-card-bg);
  border:           none;
  border-radius:    var(--border-radius-card);
  height:           100%;
  width:            100%;
  overflow:         visible;
  box-shadow:       var(--shadow-elevation-1);
}

/* "Always White Flashcards" Appearance setting (Profile →
   theme-manager.js's applyWhiteCards()) — same reasoning as
   study.css's :root[data-white-cards="true"] .study-card-face
   rule: overriding the TOKENS (not each color property
   individually) means every descendant that reads
   --color-card-bg/--color-card-text (the textarea, anything
   added here later) automatically stays readable too. Values
   are theme.css's own light-mode definitions of
   --ios-secondarySystemGroupedBackground/label — not new
   colors, just this canvas pinned to what light mode already
   looks like. */
:root[data-white-cards="true"] .card-canvas {
  background-color:  #FFFFFF;
  --color-card-bg:   #FFFFFF;
  --color-card-text: #000000;
}

/* ── CARD TEXT INPUT ──────────────────────────────────
   The textarea inside each card face.
   background: transparent lets the card canvas
   background color show through. */

.card-canvas__text {
  width:       100%;
  height:      100%;
  background:  transparent;
  border:      none;
  color:       var(--color-card-text);
  font-family: var(--font-primary);
  font-size:   var(--font-size-body);
  padding:     16px;
  text-align:  center;
  resize:      none;
  /* resize: none = removes the browser's default
     drag handle in the bottom-right corner */
  outline:     none;
  line-height: 1.6;
  position:    relative;
  z-index:     1;
  overflow-y:  auto;
  overflow-x:  hidden;
  /* Textareas scroll internally by default once content
     exceeds their height, but that default isn't
     guaranteed identical across every browser — set
     explicitly so long question/answer text is always
     reachable by scrolling instead of silently cut off. */
  /* z-index: 1 places text BELOW the symbol layer.
     z-index (CSS property) controls depth order —
     higher number = closer to the viewer. */
}

/* ── SYMBOL LAYER ─────────────────────────────────────
   Transparent overlay sitting on TOP of the text.
   Symbols dropped onto the card live inside here.

   pointer-events: none lets all clicks pass through
   this layer down to the textarea below it, EXCEPT
   on individual placed symbols which re-enable their
   own pointer events so they can be dragged. */

.symbol-layer {
  position:       absolute;
  top:            0;
  left:           0;
  width:          100%;
  height:         100%;
  pointer-events: none;
  z-index:        2;
  /* z-index: 2 places symbols visually above text */
}

/* ── PLACED SYMBOL ────────────────────────────────────
   Each individual symbol that has been dropped
   onto the card canvas. */

.placed-symbol {
  position:        relative;
  cursor:          grab;
  user-select:     none;
  /* user-select: none prevents text highlight
     when dragging the symbol */
  pointer-events:  all;
  /* Re-enables pointer events on this symbol only,
     overriding the none set on .symbol-layer */
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  padding:         14px 14px 4px 4px;
  /* Extra top-right padding makes room for the
     delete button in the top-right corner */
  transition:      box-shadow 0.15s ease;
}

.placed-symbol:active {
  cursor: grabbing;
}

/* Show the delete button only on hover */
.placed-symbol:hover .placed-symbol__delete {
  opacity: 1;
}

/* Touch devices have no hover state to reveal this through —
   without this it stays invisible (opacity: 0) and effectively
   untappable on mobile, even though it's still there and the
   JS behind it works fine. */
@media (hover: none) {
  .placed-symbol__delete {
    opacity: 1;
  }
}

/* ── EMOJI INSIDE PLACED SYMBOL ───────────────────────
   pointer-events: none lets clicks fall through
   the emoji image to the draggable wrapper behind */

.placed-symbol__emoji {
  display:        block;
  pointer-events: none;
  line-height:    1;
  flex-shrink:    0;
}

/* Twemoji (Twitter's open-source Apache 2.0 licensed
   emoji image library) renders emoji as <img> tags */
.placed-symbol__emoji img {
  display:        block;
  pointer-events: none;
  width:          32px;
  height:         32px;
}

/* ── DELETE BUTTON ON PLACED SYMBOL ───────────────────
   Small × button in the top-right corner of each
   placed symbol. Hidden until hover. */

.placed-symbol__delete {
  position:         absolute;
  top:              0;
  right:            0;
  width:            18px;
  height:           18px;
  background-color: var(--ios-systemRed);
  color:            #ffffff;
  border:           none;
  border-radius:    50%;
  font-size:        10px;
  cursor:           pointer;
  opacity:          0;
  transition:       opacity 0.2s ease;
  display:          flex;
  align-items:      center;
  justify-content:  center;
  z-index:          999;
  pointer-events:   all;
}

/* Custom PNG (Portable Network Graphics) symbol image */
.placed-symbol__img {
  object-fit:     contain;
  pointer-events: none;
}


/* ── EXTRACT TEXT TOOLBAR ─────────────────────────────
   Wraps the Extract Text button + its status message.
   justify-content: flex-end pushes both to the right
   side of the row.                                    */
.ocr-toolbar {
  display:         flex;
  align-items:     center;
  justify-content: flex-end;
  gap:             10px;
  width:           100%;
}


/* ══════════════════════════════════════════════════════
   CONFIDENCE + SCAN TEXT ROW  ← UPDATED

   LAYOUT:
   ┌──────────────────────────────────────────┐
   │  Confidence: ① ② ③ ④ ⑤   📷 Scan Text │
   └──────────────────────────────────────────┘

   justify-content: space-between pushes the
   confidence group to the LEFT and the Scan Text
   button to the RIGHT, both on the same line.
   ══════════════════════════════════════════════════════ */

.confidence-row {
  display:         flex;
  flex-direction:  row;
  align-items:     center;
  justify-content: space-between;
  /* space-between = max gap between left and right groups */
  gap:             12px;
  padding:         4px 0;
  width:           100%;
  flex-wrap:       nowrap;
  /* nowrap = forces everything onto ONE line.
     flex-wrap (CSS property) controls whether flex
     children wrap to a new line when they run out
     of room. nowrap prevents that. */
}

/* ── LEFT SIDE: label + numbered buttons ──────────── */

.confidence-left {
  display:     flex;
  flex-direction: row;
  align-items: center;
  gap:         8px;
  flex-shrink: 0;
  /* flex-shrink: 0 = this group will not compress
     to make room for other flex children */
}

.confidence-row__label {
  font-size:   var(--font-size-small);
  color:       var(--color-text-secondary);
  white-space: nowrap;
  /* white-space: nowrap = keeps "Confidence:" on
     one line, never wraps to a second line */
}

.confidence-row__buttons {
  display: flex;
  gap:     6px;
}

/* Individual confidence score buttons 1–5 */
.confidence-btn {
  width:            36px;
  height:           36px;
  border-radius:    50%;
  border:           var(--border-width) solid var(--color-border);
  background-color: var(--color-card-bg);
  color:            var(--color-text-primary);
  font-weight:      bold;
  cursor:           pointer;
  transition:       all 0.2s ease;
  font-size:        14px;
  flex-shrink:      0;
}

/* Active / selected confidence button */
.confidence-btn--active {
  border-color: var(--color-accent-amber);
  color:        var(--color-background);
  transform:    scale(1.15);
}

/* Each score level gets its own active color.
   These colors come from theme.css. */
.confidence-btn--1.confidence-btn--active {
  background: var(--color-confidence-1);
}
.confidence-btn--2.confidence-btn--active {
  background: var(--color-confidence-2);
}
.confidence-btn--3.confidence-btn--active {
  background: var(--color-confidence-3);
}
.confidence-btn--4.confidence-btn--active {
  background: var(--color-confidence-4);
}
.confidence-btn--5.confidence-btn--active {
  background: var(--color-confidence-5);
}

.confidence-row__current-label {
  font-size:  var(--font-size-small);
  color:      var(--color-accent-amber);
  font-style: italic;
}

/* ── RIGHT SIDE: Scan Text button ─────────────────── */

.btn--ocr {
  /* Size: shrinks to fit the text "📷 Scan Text" */
  display:          inline-flex;
  align-items:      center;
  gap:              6px;
  padding:          7px 14px;
  white-space:      nowrap;
  /* white-space: nowrap keeps the label on one line */

  /* Filled accent button, matching .btn */
  background-color: var(--color-accent-amber);
  color:            var(--color-button-text);
  border:           none;
  border-radius:    var(--border-radius);
  font-family:      var(--font-primary);
  font-size:        var(--font-size-small);
  font-weight:      600;
  cursor:           pointer;
  flex-shrink:      0;
  /* flex-shrink: 0 = button never gets squished */
  transition:       opacity 0.2s ease;
}

.btn--ocr:hover {
  opacity: 0.85;
}

.btn--ocr:active {
  opacity: 0.7;
}

/* OCR (Optical Character Recognition) status message
   displayed next to the button while scanning */
.ocr-status {
  font-size: var(--font-size-small);
}

.ocr-status--loading {
  color: var(--color-accent-amber);
}

.ocr-status--success {
  color: var(--color-confidence-5);
}

.ocr-status--error {
  color: var(--color-confidence-1);
}


/* ══════════════════════════════════════════════════════
   SUGGESTION BAR
   FILE: styles/card-editor.css

   LAYOUT:
   ┌──────────────────────────────────────────────────┐
   │  ✨  😊 🧬 🔬 🌿 💧 🦠 🥚 🍃 🌺 🍎 → (scrolls)   │
   └──────────────────────────────────────────────────┘

   HOW IT WORKS:
   A single row that scrolls horizontally instead of
   wrapping into a fixed-height, clipped 2-row grid — the
   old wrapped layout silently hid any suggestion past the
   2nd row with no way to reach it. Everything is reachable
   here, just swipe sideways.
   ══════════════════════════════════════════════════════ */

.suggestion-bar {
  display:          flex;
  align-items:      center;
  gap:              8px;
  padding:          8px 10px;
  min-height:       52px;

  background-color: var(--ios-tertiarySystemFill);
  border-radius:    var(--border-radius);
  width:            100%;
  box-sizing:       border-box;
  /* box-sizing: border-box = padding and border are
     included inside the declared width, so the bar
     never overflows its container */
}


/* ── SPARKLE LABEL ────────────────────────────────────
   Locked to the left, never shrinks.               */

.suggestion-bar__label {
  display:     flex;
  flex-shrink: 0;
  color:       var(--color-accent-amber);
  /* --color-accent-amber = the app's primary/accent color
     token (despite the name — see theme.css). The glow
     below already used the accent tint tokens; the sparkle
     icon itself was still plain muted gray, so it didn't
     actually read as "accent-colored" the way the glow did. */
  cursor:      default;

  /* Breathing glow animation (defined below) */
  animation:   sparkle-breathe 2.4s ease-in-out infinite;
}


/* ── SUGGESTION ITEMS ROW ─────────────────────────────
   Single row, scrolls horizontally instead of wrapping —
   see the file-level comment above for why.          */

.suggestion-bar__items {
  display:          flex;
  flex-wrap:        nowrap;
  align-items:      center;
  gap:              6px;
  flex:             1;
  min-width:        0;
  overflow-x:       auto;
  overflow-y:       hidden;
  scrollbar-width:  none;   /* Firefox */
}

.suggestion-bar__items::-webkit-scrollbar {
  display: none;             /* Chrome, Safari */
}


.suggestion-placeholder {
  font-size:   var(--font-size-footnote);
  color:       var(--color-text-secondary);
  font-style:  italic;
  white-space: nowrap;
}


/* ── INDIVIDUAL SUGGESTION ITEM ───────────────────────
   Small draggable circular chips — round rather than
   the palette grid's rounded squares, so suggestions
   read as visually distinct from browsing the library. */

.suggestion-item {
  display:          inline-flex;
  align-items:      center;
  justify-content:  center;
  width:            38px;
  height:           38px;
  border-radius:    50%;
  cursor:           grab;
  flex-shrink:      0;
  background-color: var(--color-card-bg);
  border:           none;
  box-shadow:       var(--shadow-elevation-1);
  transition:        background-color 0.15s ease,
                     transform        0.1s ease;
}

.suggestion-item:hover {
  background-color: var(--ios-secondarySystemFill);
  transform:         scale(1.06);
}

.suggestion-item:active {
  cursor:    grabbing;
  transform: scale(0.94);
}


/* Emoji character rendered as a Unicode (Universal
   Character Encoding standard) text node          */
.suggestion-item__emoji {
  font-size:      20px;
  line-height:    1;
  pointer-events: none;
  /* pointer-events: none lets the drag event
     register on the parent wrapper, not the
     emoji character itself                         */
}


/* Custom PNG (Portable Network Graphics) image
   inside a suggestion item                        */
.suggestion-item__img {
  width:          22px;
  height:         22px;
  object-fit:     contain;
  pointer-events: none;
}


/* ══════════════════════════════════════════════════════
   SPARKLE BREATHING GLOW ANIMATION

   @keyframes defines what the element looks like
   at each stage of the animation:
     0%   = start  (dim glow, full opacity reduced)
     50%  = peak   (bright glow, full opacity)
     100% = end    (matches 0% for a seamless loop)

   drop-shadow(x y blur color):
     x    = horizontal offset — 0 = centered
     y    = vertical offset   — 0 = centered
     blur = how wide/soft the glow spreads
     color= glow color with alpha transparency

   transform: scale() is intentionally held at 1.0
   throughout — size does not pulse, only the glow
   and opacity animate.
   ══════════════════════════════════════════════════════ */

@keyframes sparkle-breathe {
  /* Both keyframes deliberately stack the SAME 3 drop-shadow
     layers in the SAME order (white core, inner green, outer
     green) — only their blur radius/opacity/color-alpha
     change between the two. Animating "filter" only
     interpolates smoothly when both ends have a matching
     number/order of filter functions; the previous version
     had 1 layer at rest and 3 at the peak, which the browser
     can't blend continuously — it has to pop the missing
     layers in/out partway through, which showed up as a
     sudden, wrong-looking color flick mid-breath. */
  0%, 100% {
    filter:    drop-shadow(0 0 1px rgba(255, 255, 255, 0.3))
               drop-shadow(0 0 4px var(--tint-accent-strong))
               drop-shadow(0 0 4px var(--tint-accent-strong));
    transform: scale(1.0);
    opacity:   0.85;
  }
  50% {
    /* Three stacked drop-shadows for a white-hot core that
       fades outward to green, instead of a flat green glow:
       a tight near-white highlight right at the icon, then
       two widening green layers for the outer halo. White is
       intentionally a literal color here (not a token) — it's
       the highlight itself, not a themed surface/accent. */
    filter:    drop-shadow(0 0 3px rgba(255, 255, 255, 0.95))
               drop-shadow(0 0 10px var(--tint-accent-strong))
               drop-shadow(0 0 20px var(--tint-accent-strong));
    transform: scale(1.0);
    opacity:   1.0;
  }
}