/* Sam's article — Hang a Gallery Wall Straight the First Time
 * H1 is Sam's canon headline from her voice spec.
 * Shape: Crumbs, Hero, Lede, WhatYouNeed (the kit), Steps (4), Redo (already-crooked rescue), Affiliate, Signoff.
 * No HotTakes — the rescue section carries the opinion instead.
 * Affiliate: /go/sam-laser-level, rel=sponsored nofollow, disclosure directly below.
 * Exactly one affiliate anchor on the page, in the Affiliate card only.
 */

const SamSays = ({ children }) => (
  <div className="sa-step-says">
    <span className="who">- Sam</span>
    <p>{children}</p>
  </div>
);

const heroImage = "cover.jpg";
const imgTemplate = "sam-fig-template.jpg";
const imgHook = "sam-fig-hook.jpg";

const Crumbs = () => (
  <nav className="sa-crumbs" aria-label="Breadcrumb">
    <div className="l">
      <a href="/">Home</a>
      <span>/</span>
      <a href="/en/contributors/sam/">Sam</a>
      <span>/</span>
      <span>Decorate</span>
      <span>/</span>
      <span style={{ color: "#EFE5CF" }}>Gallery wall</span>
    </div>
    <div className="r">
      <span>Issue 08 | Summer '26</span>
      <span className="by">written by Sam</span>
    </div>
  </nav>
);

const STATS = [
  { stat: "1", note: "reference line the whole arrangement answers to" },
  { stat: "2–3 in", note: "gap between frames — and the same gap everywhere" },
  { stat: "0", note: "holes drilled until the paper has been up for a day" }
];

const Hero = () => (
  <section className="sa-hero">
    <div className="img" style={{ backgroundImage: `url('${heroImage}')` }} />
    <div className="sa-hero-wrap">
      <div>
        <div className="sa-hero-kicker">
          <span>Sam</span>
          <span className="dot">*</span>
          <span>Walls + Decorate</span>
          <span className="dot">*</span>
          <span className="sig">written by Sam</span>
        </div>
        <h1>
          Your gallery wall is crooked and <em>everyone is too polite to say so.</em>
        </h1>
        <p className="standfirst">
          it's not that you can't hang a picture. it's that you levelled nine of them, one at a time, against each other.
        </p>
      </div>
      <div className="sa-hero-side">
        {STATS.map((s) => (
          <div className="row" key={s.stat} style={{ gap: 18, alignItems: "baseline" }}>
            <span style={{ textTransform: "none", letterSpacing: "0.03em", lineHeight: 1.45, maxWidth: "26ch" }}>{s.note}</span>
            <span className="v" style={{ flexShrink: 0, whiteSpace: "nowrap" }}>{s.stat}</span>
          </div>
        ))}
        <div className="row">
          <span>Updated</span>
          <span className="v">Aug '26</span>
        </div>
      </div>
    </div>
    <div className="sa-hero-scribble" style={{ top: "17%", bottom: "auto", right: "5%" }}>
      level the <u>arrangement.</u> not the frames.
      <svg viewBox="0 0 60 30" fill="none">
        <path d="M2 22 C 12 8, 28 4, 56 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
        <path d="M48 6 L 56 12 L 50 20" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none" />
      </svg>
    </div>
  </section>
);

const Lede = () => (
  <section className="sa-lede">
    <div className="sa-lede-wrap">
      <aside className="sa-lede-side">
        <div className="marker">In this one</div>
        <ul>
          <li>The kit</li>
          <li>Build it on the floor</li>
          <li>Paper, for a day</li>
          <li>One line</li>
          <li>The drop</li>
          <li>Already crooked?</li>
        </ul>
      </aside>

      <div className="sa-lede-body">
        <p className="dropcap">
          here's the thing nobody says out loud: a gallery wall can have every single frame perfectly level and still look wrong. i've seen it. i've made it. i stood back, checked each one with a spirit level, confirmed each one was level, and the wall still looked like it had been assembled during a mild earthquake.
        </p>
        <div className="sa-pullquote">
          <p>
            arrangements don't read as crooked because of tilt. they read as crooked because the gaps are uneven and there's no line for your eye to rest on.
          </p>
        </div>
        <p>
          levelling a frame only tells you that <em>that frame</em> isn't tilted. it says nothing about whether it's in the right place relative to the other eight. so the fix isn't a better level. it's a reference line, and about forty minutes of not drilling anything.
        </p>
      </div>

      <aside className="sa-margin">
        <span className="lab">Sam's note</span>
        <h4>Moving paper is free</h4>
        <p>
          moving a nail costs filler, sandpaper, paint and a wait. that's the entire argument for step two.
        </p>
      </aside>
    </div>
  </section>
);

const WhatYouNeed = () => (
  <section className="sa-need">
    <div className="sa-need-wrap">
      <div>
        <div className="sa-need-head">00 / The kit, most of which you own</div>
        <h2>
          The cheapest item <em>is the important one</em>
        </h2>
        <p className="body">
          it's the paper. everything else on this list is a convenience; the paper is the method. a roll of kraft or a stack of newsprint is what turns nine irreversible decisions into nine reversible ones.
        </p>
        <p className="body">
          a cross-line laser makes the reference line effortless and stays put while both your hands are busy, which is genuinely why those things earn their space. a long spirit level and a chalk line get you the same result with more walking.
        </p>

        <div className="sa-need-dont">
          <span className="lab">Do not start with</span>
          <ul>
            <li>
              A hammer
              <span className="why">the order of operations is the whole method. every hole made before the layout is settled is a hole you fill later.</span>
            </li>
          </ul>
        </div>
      </div>

      <ul className="sa-need-list">
        <li>
          <span className="item">
            kraft paper or newsprint
            <span className="why">the single most valuable item here, and the cheapest.</span>
          </span>
          <span className="qty">01</span>
        </li>
        <li>
          <span className="item">
            low-tack painter's tape
            <span className="why">not masking tape. unless you enjoy touching up paint.</span>
          </span>
          <span className="qty">02</span>
        </li>
        <li>
          <span className="item">
            a cross-line laser, or a level and chalk line
            <span className="why">you need one horizontal that stays there while your hands are full.</span>
          </span>
          <span className="qty">03</span>
        </li>
        <li>
          <span className="item">
            stud finder, hooks and anchors
            <span className="why">rated for what you're actually hanging, not for what you hope it weighs.</span>
          </span>
          <span className="qty">04</span>
        </li>
        <li>
          <span className="item">
            adhesive bumpers
            <span className="why">four for a dollar, and the reason it's still straight in march.</span>
          </span>
          <span className="qty">05</span>
        </li>
      </ul>
    </div>
  </section>
);

const STEPS = [
  {
    n: "01",
    phase: "Layout | on the floor",
    title: "Build it on the floor, at wall scale.",
    wide: true,
    body: (
      <>
        <p>
          tape out the wall's usable width and height on the floor. not roughly — actually measure the wall, actually mark it on the carpet. then arrange the frames inside that outline until it looks right.
        </p>
        <p>
          the floor beats the wall for this because you can move things a hundred times for free, and because you can look down on it, which is a far more honest view than standing three feet away squinting.
        </p>
        <p>
          keep the gaps consistent — two to three inches is where most arrangements land — and keep them consistent <em>everywhere</em>, including corners and diagonals. uneven gaps are what the eye reads as "crooked" even when nothing is tilted at all. when it looks right, photograph it from directly above. that photo is your plan.
        </p>
      </>
    ),
    tip: { lab: "the honest view", text: "shoot the floor layout from directly overhead. squinting sideways at a wall is how bad arrangements get approved." }
  },
  {
    n: "02",
    phase: "Templates | paper first",
    title: "Paper templates, and a day of living with them.",
    flip: false,
    body: (
      <>
        <p>
          draw round every frame on kraft paper and cut the shapes out. mark the hanging point on each template — more on that measurement in a moment.
        </p>
        <p>
          tape the templates up in the arrangement from your photo. then walk away and leave them there for a day.
        </p>
        <p>
          this feels like an unnecessary step and it's the step that saves you. paper on a wall tells you things the floor can't: that the group sits too high, that it drifts left of the sofa, that it fights with the light switch, that the big one should be a row down. you'll move at least two of them.
        </p>
      </>
    ),
    fig: { img: imgTemplate, tag: "Fig 01 | Templates", cap: "nine reversible decisions. leave them up overnight and at least two will move." },
    says: "moving paper is free. moving a nail is filler, sandpaper, paint and a wait."
  },
  {
    n: "03",
    phase: "The line | one, for everything",
    title: "One reference line for the whole group.",
    wide: true,
    body: (
      <>
        <p>
          this is the actual technique, and it's what separates a gallery wall from a collection of individually level pictures.
        </p>
        <p>
          pick one horizontal that runs through the arrangement. galleries conventionally set the centre of a hang somewhere around fifty-seven to sixty inches from the floor — roughly average eye level — which is a good starting point, though a wall above a sofa wants the group anchored to the furniture rather than to a number.
        </p>
        <p>
          then put that line on the wall and relate <em>every</em> frame to it: tops aligned to it, bottoms aligned to it, or the line running through the centres of a row. not to its neighbour. a wall where each frame is levelled against the one beside it accumulates error across the group, and by frame nine you're an inch out and you can see it without being able to say why.
        </p>
      </>
    ),
    tip: { lab: "why a laser, specifically", text: "it holds the line across the full width while both of your hands are busy holding a frame. that's the whole pitch. a chalk line does the same job and can't be nudged." }
  },
  {
    n: "04",
    phase: "The drop | and the wall behind it",
    title: "The drop is the measurement nobody takes.",
    flip: true,
    body: (
      <>
        <p>
          the classic failure: you mark where the top of the frame goes, put the hook there, hang the picture, and it sits an inch and a half lower than planned.
        </p>
        <p>
          that gap is the drop. hook the wire with a finger and pull it taut toward the top of the frame, the way it'll sit under its own weight, then measure from the taut wire to the top edge. that number — usually an inch to three — is how far <em>below</em> your top-edge mark the hook goes. do it per frame; wires are cut to different lengths and stretch differently.
        </p>
        <p>
          then hardware, matched to weight and wall: picture hooks into drywall for light frames, proper anchors for heavier ones, masonry fixings for brick, and a stud wherever the layout lets you hit one. on anything wide, use two hooks set well apart instead of one in the middle — a single hook lets the frame rotate, and it will, every time somebody closes a door. bumpers on the bottom corners.
        </p>
      </>
    ),
    warn: { lab: "Flatly", text: "if the drill hits something that feels wrong — sudden resistance, a different sound, anything unexpected — stop. immediately. that's either a pipe or a wire and neither of those is your friend today." },
    fig: { img: imgHook, tag: "Fig 02 | The drop", cap: "the mark is where the top edge lands. the hook goes the drop distance below it." }
  }
];

const Step = ({ data }) => (
  <article
    className={`sa-step ${data.flip ? "flip" : ""}`}
    style={data.wide ? { gridTemplateColumns: "1fr", maxWidth: 880 } : undefined}
  >
    <div className="sa-step-text">
      <div className="sa-step-meta">
        <span className="sa-step-num">{data.n}</span>
        <span className="sa-step-phase">{data.phase}</span>
      </div>
      <h3>{data.title}</h3>
      <div className="sa-step-body">{data.body}</div>
      {data.tip && (
        <div className="sa-step-tip">
          <span className="lab">{data.tip.lab}</span>
          <p>{data.tip.text}</p>
        </div>
      )}
      {data.warn && (
        <div className="sa-step-warn">
          <span className="lab">{data.warn.lab}</span>
          <p>{data.warn.text}</p>
        </div>
      )}
    </div>
    {data.fig && (
      <figure className="sa-step-fig">
        <div className="frame">
          <span className="tag">{data.fig.tag}</span>
          <img src={data.fig.img} alt="" loading="lazy" />
        </div>
        <figcaption>{data.fig.cap}</figcaption>
        {data.says && <SamSays>{data.says}</SamSays>}
      </figure>
    )}
  </article>
);

const Steps = () => (
  <section className="sa-steps">
    <div className="sa-steps-wrap">
      <header className="sa-steps-head">
        <h2>
          Floor, paper, line, <em>drop.</em>
        </h2>
        <span className="count">04 MOVES | AND ONLY THE LAST ONE USES A DRILL</span>
      </header>
      {STEPS.map((s) => (
        <Step key={s.n} data={s} />
      ))}
    </div>
  </section>
);

const AlreadyCrooked = () => (
  <section className="sa-redo">
    <div className="sa-redo-wrap">
      <div className="sa-redo-side">
        it's already up and it's already crooked
        <svg viewBox="0 0 80 60" fill="none">
          <path d="M5 44 C 20 18, 46 10, 75 26" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" />
        </svg>
      </div>
      <div>
        <h2>
          You don't have to <em>start over.</em>
        </h2>
        <p>
          <strong>Bumpers first.</strong> a frame that keeps tilting is usually pivoting on one hook. an adhesive bumper on each bottom corner adds friction and very often fixes the entire complaint for about a dollar.
        </p>
        <p>
          <strong>Then a second hook.</strong> add one a hand's width from the first, on the same line. two points can't rotate. it's a smaller hole than moving the frame is.
        </p>
        <p>
          <strong>Then, only if you must, move it.</strong> and before you do — put the paper templates back up and check whether it's actually that frame. quite often the one you dislike is fine, and the one next to it is the problem.
        </p>
      </div>
    </div>
  </section>
);

const Affiliate = () => (
  <section
    style={{
      background: "var(--sa-bg-soft)",
      borderTop: "1px solid var(--sa-rule)",
      borderBottom: "1px solid var(--sa-rule)",
      padding: "56px 24px"
    }}
  >
    <div
      style={{
        maxWidth: 780,
        margin: "0 auto",
        background: "var(--sa-bg-card)",
        border: "1px solid var(--sa-rule)",
        borderLeft: "3px solid var(--sa-marker)",
        borderRadius: 4,
        padding: "32px 34px"
      }}
    >
      <span
        style={{
          fontFamily: "'JetBrains Mono', monospace",
          fontSize: 10,
          letterSpacing: "0.3em",
          textTransform: "uppercase",
          color: "var(--sa-marker)"
        }}
      >
        The tool that holds the line
      </span>
      <p
        style={{
          fontFamily: "'Playfair Display', serif",
          fontSize: 23,
          lineHeight: 1.35,
          color: "var(--sa-cream)",
          margin: "14px 0 18px"
        }}
      >
        you can absolutely do this with a spirit level and a chalk line. what a cross-line laser buys you is a horizontal that stays on the wall while both of your hands are holding a frame — and self-levelling, so the line is right even when the shelf you set it on isn't.
      </p>
      <a
        href="/go/sam-laser-level"
        rel="sponsored nofollow"
        style={{
          display: "inline-block",
          background: "var(--sa-marker)",
          color: "#100E0B",
          fontFamily: "'DM Sans', sans-serif",
          fontWeight: 700,
          fontSize: 14,
          letterSpacing: "0.02em",
          textDecoration: "none",
          padding: "12px 26px",
          borderRadius: 999
        }}
      >
        laser levels →
      </a>
      <p
        style={{
          fontFamily: "'DM Sans', sans-serif",
          fontSize: 12,
          lineHeight: 1.5,
          color: "var(--sa-mute)",
          margin: "18px 0 0"
        }}
      >
        some links on this page are affiliate links — if you buy through one, we earn a commission at no extra cost to you.
      </p>
    </div>
  </section>
);

const Signoff = () => (
  <section className="sa-signoff">
    <div className="sa-signoff-wrap">
      <div>
        <h2>
          Not a hanging skill. <em>A layout and one line.</em>
        </h2>
        <p>
          a gallery wall is a floor layout, a day of paper, and one horizontal everything answers to. and if it's still crooked after all that, nobody's going to say anything — which is what makes it worse.
        </p>
        <div className="sig">— sam</div>
        <div className="ctas" style={{ marginTop: 28 }}>
          <a href="/en/contributors/sam/" className="btn primary">
            More from Sam
          </a>
          <a href="/contact/" className="btn ghost">
            Ask Sam a question
          </a>
        </div>
      </div>
      <div className="sa-readnext">
        <span className="lab">Read next</span>
        <a href="/en/contributors/sam/floating-shelves-look-hard-theyre-not/">
          <span>Floating shelves look hard. They're not.</span>
          <span className="m">SAM</span>
        </a>
        <a href="/en/contributors/sam/kitchen-organization/">
          <span>Organize a kitchen you actually cook in</span>
          <span className="m">SAM</span>
        </a>
        <a href="/en/contributors/sam/how-to-hang-something-heavy-without-asking-anyone-for-help/">
          <span>How to hang something heavy without asking for help</span>
          <span className="m">SAM</span>
        </a>
        <a href="/en/contributors/sam/">
          <span>All of Sam's guides</span>
          <span className="m">PROFILE</span>
        </a>
      </div>
    </div>
  </section>
);

const Article = () => (
  <div className="sa">
    <Crumbs />
    <Hero />
    <Lede />
    <WhatYouNeed />
    <Steps />
    <AlreadyCrooked />
    <Affiliate />
    <Signoff />
  </div>
);

ReactDOM.createRoot(document.getElementById("root")).render(<Article />);
