Chat Control: 1984 Was a Warning, Not a Roadmap

On this page

George Orwell wrote his book 1984 as a warning, not an instruction manual. Apparently the EU Commission read it as the latter. Chat Control is the nickname for an EU legislative proposal that would force messaging apps, email providers and cloud services to scan every private message before it gets encrypted. The official pitch is “detecting child sexual abuse material.” The actual mechanism is client-side scanning of all your communications, on your own device, before the padlock even closes. The telescreen, but in your pocket.

It was first proposed by EU Commissioner Ylva Johansson in May 2022. The European Parliament’s civil liberties committee gutted the mass-scanning provisions in November 2023. It came back. It got rebranded. And here we are again in 2026 watching the Council of the EU try to push infrastructure for the same thing through a different door.

If that sounds paranoid, read on. The receipts are real.

What It Actually Does

The proposal requires service providers to scan messages, photos, videos and links for “known” and “unknown” abuse material, plus “grooming” detection powered by AI. In practice this means:

  • Every message you send gets scanned on your device before encryption
  • An AI model decides whether the content is suspicious
  • Flagged content gets forwarded to an EU center and then to national police

The joint opinion from the European Data Protection Board and Supervisor expressed serious concerns about the impact on individuals’ privacy and personal data. Privacy advocates like Patrick Breyer have consistently warned that this marks the end of privacy in digital correspondence.

AI detection is not precise. Family vacation photos, video calls with doctors, intimate text messages between adults, all of these get flagged routinely. The law does not stop that problem. It funds it.

Rebranded Until It Sticks

After the pushback in 2023, the EU did not drop the idea. It renamed it.

  • Chat Control (May 2022): scan everything to protect children
  • Going Dark (Spring 2023 to Nov 2024): a “High Level Group” producing 42 recommendations for law enforcement access to encrypted data, this time emphasizing terrorism and organized crime instead
  • ProtectEU (April 2025): incorporating those same recommendations into a broader internal security strategy
  • November 2025: the EU Council reaches a position on Chat Control that removes mandatory scanning but quietly builds the infrastructure for future surveillance

Same technical goal, different justification each time. When one narrative loses public support, the next one shows up with a fresh PR department. Rename it until nobody can remember what it used to be called or what it actually does.

The “Think of the Children” Framing Was Never the Point

Here is the tell. If this were actually about child safety, governments would welcome open public debate about mass surveillance. Instead they are actively suppressing it.

In November 2025, Mullvad released an anti-surveillance ad called “And Then?”. It aired in Germany, Sweden and the US. The UK blocked it. Clearcast, the British advertising clearance body (an industry group, notably, rather than a state entity), claimed the ad “lacks clarity” and that mentions of violent criminals were “inappropriate.” Translation: you cannot run a 30-second TV spot in the UK criticizing mass surveillance.

Mullvad then tried to put QR codes in the London Underground pointing to the banned ad. Transport for London blocked that too, reasoning that you cannot encourage people to watch a banned commercial.

Meanwhile, in January 2025, the UK Home Office issued a Technical Capability Notice under the Investigatory Powers Act demanding Apple create a backdoor to encrypted iCloud data. Apple disabled Advanced Data Protection (ADP) for UK users the following month rather than comply. ADP is the end-to-end encryption tier covering iCloud backups, photos, notes and more. Without it, Apple holds the encryption keys and can be compelled to hand over your data.

A system that censors ads criticizing surveillance and secretly orders backdoors in consumer hardware is not acting on behalf of abused children. It is acting on behalf of itself.

Who Actually Wants This to Succeed?

If you want to understand who truly benefits from this architecture of control, you do not have to look far. Take Peter Thiel, one of the most powerful men on the planet, as just one highly visible example. As documented in a comprehensive analysis of his career and worldview from the Volksgeist YouTube channel, the billionaire co-founder of Palantir has completely lost faith in democracy, openly arguing that the influence of ordinary citizens is an obstacle to unrestricted capitalism. In a 2009 essay for the Cato Institute, he put it plainly: “I no longer believe that freedom and democracy are compatible.” He went on to complain that welfare and women’s suffrage had made “capitalist democracy” into an oxymoron. By funding mass surveillance technology, military tools, and specific political leaders, his goal seems to be to bypass democratic institutions and shift power to a technocratic, corporate elite.

Thiel is not merely theorizing. He built Palantir, now valued at over $440 billion, into the backbone of Western surveillance infrastructure, with contracts spanning the CIA, the US Department of Defense, ICE, Europol, and police forces across Europe. In the UK alone, Palantir’s Gotham platform is being piloted across nine police forces, integrating criminal records, mental health reports, financial activity, and political views into searchable profiles. A Palantir employee was also directly linked to Cambridge Analytica’s harvesting of 87 million Facebook profiles, with whistleblower Christopher Wylie testifying that senior Palantir staff helped build the targeting models.

Thiel is far from alone. The push for mass digital surveillance is a coordinated effort driven by a complex network of state governments, law enforcement agencies, and a highly lucrative surveillance-industrial complex, each with their own agenda.

Law enforcement and intelligence agencies like Europol and the “Five Eyes” alliance have been pushing a “Going Dark” narrative for years, arguing that end-to-end encryption makes them blind to crime. For these agencies, client-side scanning is the ultimate master key, allowing them to bypass encryption entirely for administrative convenience.

Then there is the commercial lobby. Organizations like the US-based group Thorn present themselves as charities protecting children, yet they simultaneously build and sell proprietary AI-driven scanning software like “Safer.” Thorn aggressively lobbied EU commissioners to pass Chat Control, spending over $630,000 on lobbying in a single year alone. If the EU forces tech companies to scan all messages, these vendors stand to make a fortune licensing their algorithms to platforms scrambling to comply.

Ideologues, agencies, and lobbyists. Different motives, same machine. And once it is built, what it gets used for is no longer a technical question.

Mission Creep Is the Whole Game

Every single time surveillance infrastructure gets built “for a narrow purpose,” it expands. Every time.

  • Sweden passed the FRA law in 2008 promising to only monitor external threats. In May 2021 the European Court of Human Rights ruled it violated fundamental rights. By September 2021, the Swedish government was already proposing expansions to the law anyway.
  • Cambridge Analytica got 87 million Facebook profiles and used them to target voters in the 2016 US election
  • In 2022, four EU governments were documented using Pegasus spyware against journalists and opposition figures, with a fifth under investigation

Once the pipes exist, “what they are used for” becomes a political decision, not a technical limit.

And the creep does not stop at the application layer. When surveillance mandates hit messaging apps, the pressure inevitably trickles down into the infrastructure those apps run on: the operating system, the package manager, the init system. That is where this gets truly insidious.

The Open Source Casualty Nobody Talks About

Article 6 of the proposal requires “software application stores” to verify user ages and block minors from accessing communication software. That language threatens to accidentally nuke how open source distribution works.

Red Hat’s RPM repositories, Fedora’s mirrors, Debian’s package system, F-Droid, the Arch User Repository, almost every Linux distro’s distribution network could be caught in the crossfire. These are not “application stores” with user accounts. They serve anonymous machines. There is no concept of “the user” at the infrastructure level, because the user could be a refrigerator, a CI runner or a Japanese developer behind a VPN.

Complying would mean redesigning global software distribution from scratch. In practice, services would just shut down EU access. Sloppy law, gigantic consequences.

This is not theoretical anymore. In March 2026, a contributor submitted a pull request to systemd, the init system that boots nearly every modern Linux distribution, adding a birthDate field to its user database for age verification compliance. A Microsoft-employed maintainer merged it. It generated 945 comments and massive backlash. When the community submitted a revert, Poettering closed it without merging, calling the field “optional.” The same contributor then submitted draft PRs to Ubuntu’s installer and Arch Linux’s setup tool. The open source world erupted.

The pressure is coming from both sides of the Atlantic simultaneously: EU Chat Control pushing age-gated app stores, and US state laws like California’s AB-1043 demanding OS-level birth date collection by January 2027. The result is that surveillance plumbing is being quietly baked into the foundations of Linux, one “optional” field at a time. As one commenter on the systemd PR put it: “birthDate in userdb is not a feature. It is the first database field governments will demand be non-optional, signed, and remotely auditable.”

What You Can Do

This is not just a technical problem or just a political one. It is both, and it needs to be fought on both fronts.

Victory, March 26, 2026. The European Parliament voted 311 to 228 to reject extending the temporary ePrivacy derogation. The legal basis for voluntary scanning expired on April 3, 2026. As of that date, platforms like Meta and Google no longer have legal authority to scan private messages in the EU. The fight is not over: trilogue negotiations (closed-door talks between Parliament, Council, and Commission) on the permanent regulation are ongoing.

Make noise. Most Europeans have never heard of Chat Control despite it affecting 450 million people. Talk about it. Find your MEP and ask how they plan to vote in the upcoming negotiations. Read Mullvad’s campaign and chatcontrol.se (Swedish) for the full receipts.

Swap your stack. The best way to support the organizations fighting this is to actually use (and where possible pay for) their tools. Here is a stack that cannot betray you even under legal pressure:

  • VPN: Mullvad. Supports anonymous cash and cryptocurrency payments and does not require an email address to sign up. Look into their DAITA defense against AI traffic analysis and multihop WireGuard for layered routing. If you want to run your own, WireGuard is a lightweight, auditable VPN protocol you can set up on any server in minutes. Tailscale wraps WireGuard in zero-config mesh networking, and if you do not want to trust their coordination server, Headscale is an open-source, self-hosted replacement.
  • Browser: Stay off Chrome and Edge, which exist to feed data back to Google and Microsoft. Use Firefox or Mullvad Browser for daily use, and Tor Browser from the Tor Project for anything sensitive.
  • Ad and tracker blocking: uBlock Origin in your everyday browser. Open source, no allow-lists sold to the highest bidder, blocks trackers and fingerprinters alongside ads.
  • Messaging: Signal for end-to-end encrypted conversations. Session if you want to go further: no phone number required, decentralized, and messages are routed through an onion network so there is no central server to serve with a scanning order.
  • Mail and calendar: Tuta or Proton. Both encrypt your inbox at rest so they cannot read it even if compelled to.
  • Email aliasing: addy.io or SimpleLogin (now part of Proton). Give every service a unique email alias that forwards to your real inbox. If one gets breached or sold, deactivate it without touching anything else. Prevents cross-service identity correlation, which is one of the easiest ways to build a profile on someone.
  • Search and AI: DuckDuckGo for web search. Duck.ai when you want to query an LLM without the prompts being tied to an account or used for training.
  • Cloud storage and backups: Syncthing syncs files directly between your devices over an encrypted connection with no server in the middle. No account, no cloud, no third party that can be compelled to hand over your data. When you do need to push files somewhere else, rclone encrypts on the fly and supports everything from S3 and SFTP to Google Drive, Dropbox, and dozens of other backends. For backups, Kopia does client-side encryption with deduplication and compression, supporting the same range of targets.
  • Mobile: GrapheneOS on a Pixel. A hardened Android build that strips out Google services and gives you granular control over what each app can see.
  • Linux: pay attention to what your init system is doing with your identity data, because apparently that is something we have to worry about now.
  • Amnesic OS: Tails boots from a USB stick, routes everything through Tor, and leaves zero trace on the machine when you shut down. If you need a session that never happened, this is it.
  • Password manager: KeePassXC for offline, local-only storage. Bitwarden if you need sync across devices. Reused passwords are how a single breach chains into every account you have.
  • Two-factor authentication: Use a YubiKey or similar FIDO2 hardware key wherever possible. At minimum, use a TOTP app instead of SMS, which can be intercepted or SIM-swapped.
  • DNS: Your ISP can see every domain you visit even if you use a VPN, unless your DNS is encrypted too. Mullvad handles this automatically, but if you are self-hosting, look into DNS over HTTPS (DoH) or DNS over TLS (DoT) with a resolver you trust.

This list is a work in progress. I am actively migrating to these tools and services myself, not claiming to have it all figured out. The point is the direction, not perfection.

A note on what encryption actually protects. A VPN encrypts the pipe between you and the VPN server. Tor bounces your traffic through multiple relays. Neither one protects what you type into a service once you get there. If you log into Google over Mullvad, Google still knows it is you. If you post on Facebook through Tor, Facebook still has the post.

This matters even more in the context of Chat Control, because client-side scanning happens before encryption. The scan runs on your device, on the plaintext, before the message ever enters a VPN tunnel or a Tor circuit. Transport encryption is irrelevant to it. The only thing that protects you is the application itself refusing to scan. Your choice of messaging app and your choice of VPN are equally important, just for different threats.

Metadata is the other half of the problem. Even with encrypted content, the patterns of who talks to whom, when, and how often can reveal as much as the message itself. This is what privacy-focused browsers (Firefox with strict tracking protection, Mullvad Browser), ad blockers like uBlock Origin, and Session’s onion routing are actually defending against. Signal encrypts your messages and uses Sealed Sender to hide who sent them, but the server still sees the recipient and when you connect. When subpoenaed by a grand jury in 2021, all Signal could hand over was two timestamps: account creation date and last connection date. Session goes further by routing messages through an onion network, so the server never sees either end of the conversation.

Spread the Word: The Chat Control Button

I made a button with Gemini, in the same spirit as the CSS experiments I wrote about in my Buy Me a Lambo post. This one has a scanning CCTV eye and a dropdown linking to the main Chat Control resources. Click it to open the links.

READ MORE ABOUT CHAT CONTROL 2.0
AND WHY IT HAS TO BE STOPPED

Feel free to copy and edit it to use on your own site.

Click here to view source
<!-- 1. IMPORT FONTS (Place in <head> or at the top of your document) -->
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@500;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap" rel="stylesheet">

<!-- 2. STYLES -->
<style>
  .cc-widget-wrapper {
    position: relative;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    font-family: 'Courier New', Courier, monospace;
    /* Symmetric padding so the button (and popup) sit on the wrapper's true center */
    padding: 20px;
  }

  .cc-widget-wrapper button {
    cursor: pointer;
    font-family: inherit;
    border: none;
    outline: none;
    position: relative;
    user-select: none;
  }

  /* BUTTON STYLING */
  .btn-chatcontrol {
    font-family: 'Orbitron', sans-serif;
    background: transparent;
    color: #e0e0e0;
    font-size: 22px;
    letter-spacing: 2px;
    /* Pushes text to the right to visually center it with the camera */
    padding: 10px 30px 10px 105px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    position: relative;
    border: none;
    text-decoration: none;
    overflow: visible;
    height: 60px;
    box-sizing: border-box;
    z-index: 10; /* Ensures button is strictly above the dropdown */
    transition: 0.3s;
    text-shadow: 0 0 5px rgba(255,255,255,0.3);
  }

  .btn-chatcontrol::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(145deg, #2b2b2b, #111111);
    border: 1px solid #333;
    border-radius: 8px;
    z-index: -1;
    box-shadow: inset 0 2px 0 rgba(255,255,255,0.05), 0 4px 10px rgba(0,0,0,0.5);
    transition: 0.3s;
  }

  .btn-chatcontrol:hover {
    transform: translateY(-2px);
  }

  .btn-chatcontrol:hover::after {
    border-color: #ff0000;
    box-shadow: inset 0 2px 0 rgba(255,255,255,0.05), 0 4px 15px rgba(255,0,0,0.2);
  }

  /* ACTIVE STATE GLOW (when dropdown is open) */
  .btn-chatcontrol.active::after {
    border-color: #ff0000;
    box-shadow: inset 0 2px 0 rgba(255,255,255,0.05), 0 0 25px 5px rgba(255,0,0,0.5);
  }

  /* CAMERA SVG */
  .btn-chatcontrol svg.cc-camera {
    height: 110px;
    width: 110px;
    position: absolute;
    left: -10px;
    top: 50%;
    transform: translateY(-50%);
    filter: drop-shadow(0 5px 5px rgba(0,0,0,0.5));
    pointer-events: none;
    z-index: 10;
  }

  /* ANIMATIONS */
  @keyframes scanEye {
    0%, 85%   { transform: translate(0, 0); }
    87%, 89%  { transform: translate(-10px, -5px); }
    91%, 93%  { transform: translate(8px, 2px); }
    95%, 97%  { transform: translate(4px, -8px); }
    98%, 99%  { transform: translate(-8px, 6px); }
    100%      { transform: translate(0, 0); }
  }

  .scanning-eye {
    animation: scanEye 15s infinite cubic-bezier(0.68, -0.55, 0.27, 1.55);
    transform-origin: 50px 50px;
    transition: transform 0.15s ease-out;
  }

  .scanning-eye.is-tracking {
    animation: none;
  }

  @keyframes pulseRed {
    0% { r: 8; opacity: 0.8; }
    50% { r: 11; opacity: 1; }
    100% { r: 8; opacity: 0.8; }
  }

  .cc-camera .red-eye {
    animation: pulseRed 2s infinite ease-in-out;
  }

  /* ACTIVE LASER RING */
  .btn-chatcontrol.active .scanning-eye circle[stroke-dasharray] {
    stroke-width: 4;
    filter: drop-shadow(0 0 6px #ff0000);
  }

  /* DROPDOWN STYLING */
  .cc-dropdown {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%) translateY(0);
    width: 320px;
    max-width: 90vw;
    background: rgba(10, 10, 10, 0.95);
    border: 1px solid #333;
    border-radius: 8px;
    /* Justerad övre padding för att dra ner texten en gnutta */
    padding: 22px 14px 14px 14px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.8), 0 0 20px rgba(255, 0, 0, 0.1);
    opacity: 0;
    pointer-events: none;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 5; /* Under button */
    backdrop-filter: blur(10px);
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .cc-dropdown.active {
    opacity: 1;
    pointer-events: all;
    /* Skjuter upp rutan mer för att stänga gapet till knappen helt */
    transform: translateX(-50%) translateY(-22px);
    border-color: #ff0000;
    box-shadow: 0 10px 40px rgba(0,0,0,0.9), 0 0 30px rgba(255, 0, 0, 0.3);
  }

  .cc-dropdown h3 {
    margin-top: 0;
    margin-bottom: 14px;
    font-family: 'Share Tech Mono', monospace;
    color: #ff0000;
    font-size: 16px;
    font-weight: normal;
    text-align: center;
    text-transform: uppercase;
    letter-spacing: 1px;
    line-height: 1.4;
    border-bottom: 1px dashed #333;
    padding-bottom: 8px;
    width: 100%;
    display: block;
    box-sizing: border-box;
  }

  .link-row {
    display: flex;
    align-items: center;
    background: #000;
    margin-bottom: 8px;
    border-radius: 6px;
    border: 1px solid #222;
    transition: 0.2s;
    height: 44px;
    width: 100%;
    position: relative;
    overflow: hidden;
    box-sizing: border-box;
  }

  .link-row:hover {
    border-color: #555;
    background-color: #080808;
  }

  .link-row:last-child {
    margin-bottom: 0;
  }

  .link-details-container {
    flex-grow: 1;
    padding: 0 12px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    text-decoration: none;
    color: inherit;
    overflow: hidden;
  }

  .link-details-container .link-url {
    font-family: 'Roboto Mono', monospace;
    font-size: 16px;
    color: #ccc;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: color 0.2s;
  }

  .link-row:hover .link-url {
    color: #FFDD00;
  }

  .link-icon-container {
    width: 40px;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #080808;
    border-right: 1px solid #222;
    flex-shrink: 0;
  }

  .link-icon-container svg {
    width: 18px;
    height: 18px;
    color: #ff0000;
    filter: drop-shadow(0 0 2px rgba(255,0,0,0.5));
  }
</style>

<!-- 3. HTML STRUCTURE -->
<div class="cc-widget-wrapper">
  <!-- Main Button -->
  <button class="btn-chatcontrol" id="ccBtn" onclick="toggleCCDropdown()">
    <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" class="cc-camera">
      <defs>
        <radialGradient id="bodyGrad" cx="40%" cy="30%" r="70%">
          <stop offset="0%" stop-color="#e0e8f0" />
          <stop offset="30%" stop-color="#8ba1b8" />
          <stop offset="80%" stop-color="#1a2533" />
          <stop offset="100%" stop-color="#090f14" />
        </radialGradient>
        <radialGradient id="lensGrad" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stop-color="#2a0505" />
          <stop offset="50%" stop-color="#0d0202" />
          <stop offset="90%" stop-color="#000000" />
          <stop offset="100%" stop-color="#111" />
        </radialGradient>
        <radialGradient id="redGlow" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stop-color="#ffffff" />
          <stop offset="15%" stop-color="#ff3333" />
          <stop offset="40%" stop-color="#ff0000" />
          <stop offset="100%" stop-color="transparent" />
        </radialGradient>
        <filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
          <feGaussianBlur stdDeviation="3" result="blur" />
          <feComposite in="SourceGraphic" in2="blur" operator="over" />
        </filter>
      </defs>

      <circle cx="50" cy="50" r="45" fill="url(#bodyGrad)" />
      <circle cx="50" cy="50" r="32" fill="url(#lensGrad)" />

      <g class="scanning-eye">
        <circle cx="50" cy="50" r="16" fill="none" stroke="#ff0000" stroke-width="2" stroke-dasharray="2 3" filter="url(#glow)" opacity="0.9"/>
        <circle cx="50" cy="50" r="18" fill="none" stroke="#ff0000" stroke-width="0.5" opacity="0.5" />
        <circle cx="50" cy="50" r="9" fill="url(#redGlow)" filter="url(#glow)" class="red-eye" />
      </g>

      <circle cx="50" cy="25" r="1.5" fill="#00d5ff" filter="url(#glow)" />

      <path d="M 30 30 Q 50 20 70 30 Q 50 25 30 30 Z" fill="#ffffff" opacity="0.15" />
      <path d="M 70 70 Q 50 80 30 70 Q 50 75 70 70 Z" fill="#ffffff" opacity="0.05" />
    </svg>
    <span>CHAT CONTROL 2.0</span>
  </button>

  <!-- Dropdown -->
  <div class="cc-dropdown" id="ccDropdown">
    <h3>READ MORE ABOUT CHAT CONTROL 2.0<br>AND WHY IT HAS TO BE STOPPED</h3>

    <div class="link-row">
      <div class="link-icon-container">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a10 10 0 0 1 10 10 10 10 0 0 1-10 10 10 10 0 0 1-10-10 10 10 0 0 1 10-10m0 20a10 10 0 0 0-10-10 10 10 0 0 0 10 10m0-20a10 10 0 0 0 10 10 10 10 0 0 0-10-10"></path><circle cx="12" cy="12" r="3"></circle></svg>
      </div>
      <a href="https://matinen.com/chatcontrol" target="_blank" class="link-details-container">
        <span class="link-url">matinen.com/chatcontrol</span>
      </a>
    </div>

    <div class="link-row">
      <div class="link-icon-container">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a10 10 0 0 1 10 10 10 10 0 0 1-10 10 10 10 0 0 1-10-10 10 10 0 0 1 10-10m0 20a10 10 0 0 0-10-10 10 10 0 0 0 10 10m0-20a10 10 0 0 0 10 10 10 10 0 0 0-10-10"></path><circle cx="12" cy="12" r="3"></circle></svg>
      </div>
      <a href="https://mullvad.net/en/chatcontrol" target="_blank" class="link-details-container">
        <span class="link-url">mullvad.net/en/chatcontrol</span>
      </a>
    </div>

    <div class="link-row">
      <div class="link-icon-container">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a10 10 0 0 1 10 10 10 10 0 0 1-10 10 10 10 0 0 1-10-10 10 10 0 0 1 10-10m0 20a10 10 0 0 0-10-10 10 10 0 0 0 10 10m0-20a10 10 0 0 0 10 10 10 10 0 0 0-10-10"></path><circle cx="12" cy="12" r="3"></circle></svg>
      </div>
      <a href="https://chatcontrol.se/" target="_blank" class="link-details-container">
        <span class="link-url">chatcontrol.se</span>
      </a>
    </div>
  </div>
</div>

<!-- 4. JAVASCRIPT -->
<script>
  function toggleCCDropdown() {
    const dropdown = document.getElementById('ccDropdown');
    const btn = document.getElementById('ccBtn');
    dropdown.classList.toggle('active');
    btn.classList.toggle('active');
  }

  const btn = document.getElementById('ccBtn');
  const eye = document.querySelector('.scanning-eye');
  const svg = document.querySelector('.cc-camera');
  let isHoveringBtn = false;

  btn.addEventListener('mouseenter', () => isHoveringBtn = true);
  btn.addEventListener('mouseleave', () => isHoveringBtn = false);

  document.addEventListener('mousemove', (e) => {
    const dropdown = document.getElementById('ccDropdown');
    const isDropdownActive = dropdown && dropdown.classList.contains('active');

    if (isHoveringBtn || isDropdownActive) {
      eye.classList.add('is-tracking');

      // Calculate the center point of the camera SVG relative to the viewport
      const svgRect = svg.getBoundingClientRect();
      const centerX = svgRect.left + svgRect.width / 2;
      const centerY = svgRect.top + svgRect.height / 2;

      // Calculate distance and angle from the center to the mouse
      const dx = e.clientX - centerX;
      const dy = e.clientY - centerY;
      const distance = Math.sqrt(dx * dx + dy * dy);
      const angle = Math.atan2(dy, dx);

      // Define the maximum distance the eye can move within the lens
      const maxRadius = 12;

      // Adjust sensitivity (0.08 multiplier means it tracks smoothly as you get further)
      const radius = Math.min(distance * 0.08, maxRadius);

      const moveX = Math.cos(angle) * radius;
      const moveY = Math.sin(angle) * radius;

      eye.style.transform = `translate(${moveX}px, ${moveY}px)`;
    } else {
      // Remove inline styles to let the 15-second CSS animation resume
      if (eye.classList.contains('is-tracking')) {
        eye.classList.remove('is-tracking');
        eye.style.transform = '';
      }
    }
  });

  // Close dropdown if clicking outside
  document.addEventListener('click', function(event) {
    const dropdown = document.getElementById('ccDropdown');
    const btn = document.getElementById('ccBtn');
    if (dropdown && btn && !dropdown.contains(event.target) && !btn.contains(event.target)) {
      dropdown.classList.remove('active');
      btn.classList.remove('active');
    }
  });
</script>

Conclusion

Chat Control 2.0 is not about children. If it were, the UK would not be banning ads that oppose it and the EU would not be renaming the same proposal every 18 months. The pattern is too consistent to be accidental: build the surveillance pipes now, figure out the justification later.

The FRA precedent, the UK ad censorship, the Apple backdoor demand, the Cambridge Analytica playbook, all of these are the same story told in different fonts. Privacy is infrastructure for a free society. Once you lose it, you do not get it back by voting harder.

Orwell wrote that in the world of 1984, “nothing was your own except the few cubic centimetres inside your skull.” End-to-end encryption is the digital equivalent of those few cubic centimetres, the last private space you have. If Chat Control succeeds, that is the world we are heading toward.

 

Matinen.com

Projects and documentation on things I find interesting, captured here so I don’t forget them. But mostly to keep myself from buying another domain name.

BTC
ETH
SOL
ADA
TRX
DOGE
TON
XMR

READ MORE ABOUT CHAT CONTROL 2.0
AND WHY IT HAS TO BE STOPPED


2026-04-05