<think>
Okay, I need to implement the config_value function based on the given problem statement. Let me start by understanding the requirements.

The function takes a list of layers and a name. Each layer is a string of newline-separated lines. The layers are processed in order, from lowest to highest precedence. Each line in a layer can be ignored, an assignment, or an unset.

First, I need to process each layer. For each line in a layer, I have to check if it's ignored, an assignment, or an unset. The rules are:

- Blank lines or lines starting with a hash are ignored.
- Lines with name=value assign the value to the name.
- Lines starting with '!' followed by a name unset that name.
- Names and values are trimmed of whitespace.
- Assignments later in the same layer or later layers override earlier ones.
- The value can be empty, which is different from unset.

The function should return the effective value of the name, or None if it was never assigned or last mentioned unset.

Now, the steps I need to take:

1. Iterate through each layer in the given list.
2. For each layer, split into lines.
3. For each line in the layer, process it:
   a. Check if it's an ignored line (blank or starts with #).
   b. If not, check if it's an unset line (starts with '!' followed by name).
   c. Else, check if it's an assignment (has '=').
   d. If not, it's invalid (like a line without '=' and not unset, which is an error).
4. For each valid line, process the name and value.
5. Track the current value of the name. If an unset is encountered, the value is set to None, and any subsequent assignments will override it.
6. After processing all layers, return the current value of the name, or None if it was never set or last unset.

Now, handling the layers:

Each layer is a string. So, for each layer in layers, split into lines. Then process each line.

But wait, the layers are ordered, so the first layer is the lowest precedence, and the last is highest.

So, for each line in each layer, in order of layers, process them.

But for each line, if it's an assignment, we need to check if it's a valid line. For example, a line like "  key  =  value  " would be trimmed to "key=value".

But if a line is like "  key  =  ", then the value is empty. That's allowed.

But if a line is like "  key  ", then it's ignored.

So, the processing steps for each line:

Trim the line. If the line is empty or starts with '#', ignore.

Else, split into parts. If the line starts with '!', then the rest is the name to unset. Else, split into name and value by the '='.

But how to split? For example, a line like "key= value" would be split into name 'key' and value ' value' (trimmed).

But if the line is "key= value", after trimming, it's "key= value", so split on '=' gives name 'key' and value ' value' (trimmed to 'value').

But if the line is "key= value", then the value is ' value' (after trimming, it's 'value').

But for the unset case, the line starts with '!', so the rest is the name. For example, "!key" would unset 'key'.

But the line could be "! key" (after trimming, it's "! key" → the '!' is the first character,